Ошибка первичного ключа против выбора команды - PullRequest
0 голосов
/ 13 апреля 2011

Я создаю приложение в качестве счетчика URL. я создал таблицу для хранения URL-адреса и его количества.

CREATE TABLE [dbo].[tblurlcounter](
    [id] [bigint] IDENTITY(1,1) NOT NULL,
    [type] [varchar](500) COLLATE SQL_Latin1_General_CP1_CI_AS NULL,
    [count] [bigint] NULL,
 CONSTRAINT [PK_tblurlcounter] PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX  = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
) ON [PRIMARY]

Я создал хранимую процедуру для вставки / обновления URL в таблице. означает, что когда значение "URL" будет вставлено в эту таблицу с помощью хранимой процедуры, я проверяю, что если оно существует, обновите его счетчик, а если нет, то вставьте его в таблицу с count = 1.

моя хранимая процедура выглядит так:

declare @count int

select @count= [count] from tblurlcounter where [type] = @type
if @count > 0
begin
update tblurlcounter set [count]=@count + 1 where [type] = @type
select @count + 1

end
else 
begin
INSERT INTO [dbcounter].[dbo].[tblurlcounter]
           ([type]
           ,[count])
     VALUES
           (@type
           ,1)
end

это приложение получит от 80 000 до 100 000 показов за минуту. поэтому я хочу, чтобы моя хранимая процедура выполняла операции с хорошей скоростью. я имею в виду, что мое решение должно быть оптимизировано.

кто-то предложил мне изменить свою таблицу и создать ее поле с именем "type" (которое я использую для хранения URL) в качестве первичного ключа, а в хранимой процедуре я должен сначала попытаться вставить запись и, если она выдаст ошибку затем проверьте наличие ошибки в следующей строке и выполните операцию обновления.

, поэтому я запутался, что какой из них будет быстрее, возникнет ошибка первичного ключа, или я должен идти с запросом выбора и основываться на результате выбора, я должен выполнить операцию вставки / обновления

Теперь мне нужен совет экспертов, какой подход правильный, и если есть какой-либо другой хороший подход, то, пожалуйста, предложите мне.

спасибо

Ответы [ 4 ]

2 голосов
/ 13 апреля 2011

Для этой нагрузки вам нужно быть немного умным.Я уже писал об этом

В принципе, не тестируйте сначала: попробуйте ВСТАВИТЬ.Если это не удается, запустите обновление

https://stackoverflow.com/search?q=user%3A27535+JFDI

2 голосов
/ 13 апреля 2011

Ваш подход не будет работать должным образом, поскольку вы выполняете несколько операторов. Т.е. между этой строкой происходит:

select @count = [count] from tblurlcounter where [type] = @type

и ваш INSERT или UPDATE фактически выполняются, отдельное выполнение хранимой процедуры также может добавлять строку, так что вы можете получить два INSERTS, происходящих почти одновременно.

Вместо этого попробуйте это:

INSERT INTO [dbcounter].[dbo].[tblurlcounter]
           ([type]
           ,[count])
     VALUES
           (@type
           ,0)
WHERE NOT EXISTS(select 1 from tblurlcounter where [type] = @type)

UPDATE tblurlcounter SET [count]=[count] + 1 where [type] = @type

Это добавит новую строку, если соответствующая строка еще не существует, сочетая ВСТАВКУ с проверкой существования. Оператор обновления может выполняться безопасно, зная, что уже есть строка для обновления.

Вам также действительно нужен индекс для вашего столбца Type.

2 голосов
/ 13 апреля 2011

Вы можете просто попробовать и сделать обновление, если оно не существует, никакие строки не будут обновлены, что вы можете проверить с помощью @@rowcount.Если их нет, вы можете добавить их, иначе значение уже увеличено.Вам не нужна переменная @count, так как тогда вам придется заблокировать строку, чтобы ничто не могло изменить значение после того, как вы его присвоили, но до того, как вы обновили таблицу.

update tblurlcounter set [count] = [count] + 1 where [type] = @type

if @@rowcount = 0 
begin
  insert into tblurlcounter 
  ([type],[count])
  values
  (@type, 1)
end
0 голосов
/ 13 апреля 2011

В этой статье очень хорошо объясняется, если обновление существует, а не обновление, если не существует подход вставки.

По-видимому, из-за блокировок таблицы сделать выбор, чтобы проверить, существует ли он первым, дешевле.Таким образом мы избегаем использования обновления, которое блокировало бы гораздо больше данных, чем выбор.

http://weblogs.sqlteam.com/mladenp/archive/2007/07/30/60273.aspx

также

, которые вы можете использовать:

если существует (выберите * в tblurlcounter, где [type] = @type)

...