在大型表中,更新语句中的自增导致重复值

5

我需要重新编号表格中的行,使用了以下代码,参考自You've Been Haacked博客文章:

DECLARE @counter int
SET @counter = 0
UPDATE #myTable
SET @counter = ID = @counter + 1

这对于几条记录到几千条记录都可以正常运行,但是当我在一个包含250K+记录的SQL Server 2012(64位)实例上运行它时,在表格中会出现许多重复项(ID#1出现了12次)。总共有大约27K条记录具有重复的值。奇怪的是,大约19K个记录恰好有12个重复项(与我的计算机上的处理器数量相同)。

是什么导致了这些重复项?


1
我会说这个语句是并行执行的,而不是逐行执行的。因此计数器没有被“足够快地”递增。 - Marko Juvančič
你能发布你的查询计划吗? - dsolimano
1
这不是最好的方法。正如@GiorgiNakeuri所说,ROW_NUMBER会是一个更好的方法。您可以添加查询提示OPTION(MAXDOP 1)以防止其溢出到超过1个处理器。然而,性能可能会受到影响。 - Sean Lange
4
欢迎来到2015年。使用序列或标识列代替手动计算。 - Zohar Peled
1
这被亲切地称为“古怪更新” - 不要使用它。语法未经记录,不受支持,并且不能保护您免受由并发/并行引起的冲突。 - Aaron Bertrand
显示剩余4条评论
1个回答

5

以下代码使用并不保证有效,我相信Phil Haack会指出问题,建议丢弃。

可能的原因是并行性。该变量可能被多个线程同时操作。

奇怪的是,约有19K个重复项恰好有12个(我的计算机上有12个处理器)。

这符合上述解释。

使用ROW_NUMBER生成有效且可靠的ID:

update t
set ID = r
from (
 select *, row_number() over (order by something) r from T
) t
就像简单但明智一样。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,