2016-09-16 54 views
0

因此,我有一个存储过程,需要定期更新一个大型表,其中包含大约7000万条记录。我通常总是遵循循环更新的标准来避免锁定我的其他大型表,并且通常我没有看到性能影响太大。循环SQL Server更新语句的性能不佳

问题: 当我使用循环相比,没有循环逻辑的原始运行时我看到了10倍或20倍我的执行时间增加。

例如:

如果我运行下面的查询我会在大约150分钟更新一次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或留空。根据它,它将更新所有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

你在每一个更新做检查点? –

+0

为什么不把getdate()保存到一个变量中并使用它呢? –

+0

您是否尝试过增加50000或100000批量? –

回答

2

所以,我会怀疑这会更慢,因为在每一个循环您的查询必须找出一套记录更新,即评价是:

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) 

我还要指出的是你的第二个更新不做与第一个完全相同的事情 - 尝试在某天午夜之前运行这两者 - 第二组更新会得到不同的结果。

+0

这是发生在....我修改了查询来做手套的计算,速度急剧增加。谢谢您的帮助! – Zi0n1

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)