问题描述
|
我正在创建一个应用程序作为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”插入该表中,然后我检查其是否存在,然后更新其计数,如果不存在,则将其插入计数为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的文件)作为主键,在存储过程中,我应该首先尝试插入记录,如果它抛出错误,则在下一行检查错误并执行更新操作。
所以我很困惑哪个会更快,主键错误方法还是我应该选择查询并根据选择的结果我应该执行插入/更新操作
现在,我需要专家建议,哪种方法正确,如果有其他好的方法可用,请提出建议。
谢谢
解决方法
对于这种负载,您需要变得聪明一点。我已经在此发布了
基本上,不要先测试:尝试INSERT。如果失败,请运行更新
https://stackoverflow.com/search?q=user%3A27535+JFDI
,您可以尝试进行更新,如果不存在更新,则不会更新任何行,可以使用
@@rowcount
进行检查。如果没有,则可以添加它,否则该值已经增加。您不需要@count
变量,因为那样您就必须锁定行,因此在分配值之后但在更新表之前,没有什么可以更改该值。
update tblurlcounter set [count] = [count] + 1 where [type] = @type
if @@rowcount = 0
begin
insert into tblurlcounter
([type],[count])
values
(@type,1)
end
,当您执行多个语句时,您的方法将无法正常工作。即,在此行之间发生:
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
如果不存在匹配的行,则会添加新行,并将INSERT与存在性检查结合起来。在知道已经有一行要更新的情况下,可以安全地运行update语句。
您还确实需要在Type列上建立索引。
,本文很好地解释了如果存在更新与不存在更新的插入方法。
显然是因为有表锁,所以进行一次选择检查是否首先存在就便宜了。这样,我们避免使用更新,该更新将比选择锁定更多的数据。
http://weblogs.sqlteam.com/mladenp/archive/2007/07/30/60273.aspx
也,
您可以使用:
如果存在(从tblurlcounter中选择*,其中[type] = @type)