所以我有一个存储过程需要定期更新一个包含大约7000万条记录的大表。我通常总是遵循循环更新的标准,以避免锁定我的任何其他大表,并且我通常没有看到性能影响太大。
问题: 我看到,与没有循环逻辑的原始运行时相比,当我使用循环时,我的执行时间增加了10或20倍。
例如:
如果我要运行以下查询,我会在大约1.5分钟内更新300万条记录。
UPDATE [db1].[dbo].[Preferences]
SET LastUpdate = Getdate()
WHERE
LastUpdate >= CAST(CONVERT( Varchar(10), DATEADD(day,-1,GETDATE()), 110) as DateTime)
AND
LastUpdate < CAST(CONVERT( Varchar(10), GETDATE(), 110) as DateTime)
AND (@PreferenceID is null or @PreferenceID = PreferenceID)
这是我的常规更新语句,后面没有循环机制。基本上,参数@PreferenceID要么提供ID,要么保留为null。根据它,它将更新今天所有lastUpdate的日期或仅更新一个preferenceID。在我的测试用例中,我使用了1个preferenceID,因此正在填充@PreferenceID。
所以当我添加循环到这个语句时,它从1.5分钟到20分钟。
以下是循环语句:
BEGIN
SET ROWCOUNT 10000
UPDATE [DB1].[dbo].[Preferences]
SET LastUpdate = Getdate()
WHERE
LastUpdate >= CAST(CONVERT( Varchar(10), DATEADD(day,-1,GETDATE()), 110) as DateTime)
AND
LastUpdate < CAST(CONVERT( Varchar(10), GETDATE(), 110) as DateTime)
AND (@PreferenceID is null or @PreferenceID = PreferenceID)
WHILE @@ROWCOUNT > 0
UPDATE [DB1].[dbo].[Preferences]
SET LastUpdate = Getdate()
WHERE
LastUpdate >= CAST(CONVERT( Varchar(10), DATEADD(day,-1,GETDATE()), 110) as DateTime)
AND
LastUpdate < CAST(CONVERT( Varchar(10), GETDATE(), 110) as DateTime)
AND (@PreferenceID is null or @PreferenceID = PreferenceID)
SET ROWCOUNT 0
END
所以我的核心问题是为什么我的执行时间会因为一次循环10k记录而增加太多?我可以发布有关表结构的更多详细信息,但我不确定这是否只是一个坚定的规则,与仅仅一次完整批量更新相比,它将成为循环更新的性能影响。
提前感谢任何人可以提供的建议。
答案 0 :(得分:2)
所以,我怀疑这个速度较慢,因为在每个循环中你的查询必须找出要更新的记录集,即评估这个:
Stopping
我还会注意到,您的第二次更新与第一次更新完全不同 - 尝试在一天午夜之前运行这两种更新 - 您将在第二组更新中获得不同的结果。
答案 1 :(得分:1)
您可以将所有内容保存在变量中,并尝试循环
DECLARE @dt DATETIME = CAST(CONVERT( Varchar(10), GETDATE(), 110) as DateTime)
DECLARE @dtAdd DATETIME = CAST(CONVERT( Varchar(10), DATEADD(day,-1,GETDATE()), 110) as DateTime)
UPDATE [DB1].[dbo].[Preferences]
SET LastUpdate = @dt
WHERE
LastUpdate >= @dtAdd
AND
LastUpdate < @dt
AND (@PreferenceID is null or @PreferenceID = PreferenceID)