2017-03-23 50 views
2

我有一張包含大約10萬條記錄的表。我想在1000塊如下更新while循環中的表:在SQL的WHILE循環中運行UPDATE語句需要永久運行

DECLARE @totalRecordCount INT 
DECLARE @midCount INT 
DECLARE @Chunksize INT 

set @totalRecordCount = (SELECT COUNT(*) FROM Tabletemp) 
set @ChunkSize = CEILING(@totalRecordCount/1000)+1 -- Divide the total into 1000 chunks 
set @midcount = @totalRecordcount 
while @midcount > 0 
BEGIN 
    UPDATE top(@Chunksize) a 
    set a.x = b.x 
    FROM TableTemp a 
    INNER JOIN 
    TableTemp2 b on a.id = b.id 
    WHERE a.x is Null 

    SET @[email protected]@ROWCOUNT 
END 

我試圖把一個SELECT語句前@@ ROWCOUNT看才能到達那裏多少時間,但查詢保持運行永遠。當我用相應的@Chunksize運行單個更新語句時,它會在最大13秒內運行,但是在循環中它會一直運行。

我也用SELECT替換了UPDATE,看看循環是否正常運行,並發現它工作正常。

沒有得到爲什麼UPDATE永遠需要運行,請大家幫忙!

+0

你使用的是哪個版本的sql server? – PRABA

+2

您的查詢不是分塊的結果。它正在做一個非常大的更新。 –

+0

當你開始時,@midcount被初始化了嗎?另外,正如戈登已經提到的更新一次完成,沒有在你的代碼中分塊 – GuidoG

回答

0

這將在每個循環中更新最多1000行。我不是100%肯定,它會比1大更新更好地工作(也許如果你包括一個DELAY):

如果你在兩個表中創建一個ID索引,這可能不是必需的。然而,這是實現你正在嘗試的腳本。如果ID不是唯一的,你肯定會遇到問題。

DECLARE @midCount INT = 1 
DECLARE @Chunksize INT = 1000 

WHILE @midcount > 0 
BEGIN 
    WITH CTE as 
    (
    SELECT top(@ChunkSize) a.x, b.x newxvalue 
    FROM TableTemp a 
    JOIN TableTemp2 b 
    ON a.id = b.id 
    WHERE a.x is Null and b.x is not null 
) 
    UPDATE CTE SET x = newxvalue 

    SET @[email protected]@ROWCOUNT 
    --IF @midcount = @Chunksize WAITFOR DELAY '00:00:05' -- 5 sec delay 
END 
0

我覺得你沒有對a.x

指數在一個大的更新的情況下,也可能是一個全表掃描完成。

在塊的情況下,您將掃描每次迭代中以前已更新的所有行(因爲掃描中的行順序不會被更改)。例如。更新將使用大約NUMBER_OF_CHUNKS全表掃描完成

0

更新大塊似乎需要更長的時間,而不是更新時沒有塊,它運行得更快。還增加索引幫助。在塊

更新被幾圈不知道是什麼原因後卡住。