2017-03-23 51 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

更新大块似乎需要更长的时间,而不是更新时没有块,它运行得更快。还增加索引帮助。在块

更新被几圈不知道是什么原因后卡住。