2016-09-16 55 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)