【问题标题】:Auto Increment in update statement resulting in duplicate values on large table更新语句中的自动增量导致大表上的重复值
【发布时间】:2015-05-14 18:45:46
【问题描述】:

我需要使用You've Been Haacked blog post 中的以下代码对表中的行重新编号:

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

这适用于几条记录到几千条记录,但是当我在具有 250K+ 记录的表上的 SQL Server 2012(64 位)实例上运行它时,我最终会得到许多重复项(ID #1 出现 12 次)。总共有大约 27K 条记录具有重复值。奇怪的是,大约 19K 正好有 12 个重复(我的机器上的处理器数量相同)。

重复的原因是什么?

【问题讨论】:

  • 我会说这个语句是并行执行的,而不是逐行执行。因此,计数器不会“足够快”地递增。​​,
  • 你能发布你的查询计划吗?
  • 这不是最好的方法。正如@GiorgiNakeuri 已经说过的那样,ROW_NUMBER 将是一种更好的方法。您可以添加查询提示 OPTION (MAXDOP 1) 以防止它溢出到超过 1 个处理器上。然而,性能可能会受到影响。
  • 欢迎来到 2015。使用序列或标识列而不是自己计算。
  • 这被亲切地称为“古怪更新”——不要使用它。该语法未记录,不受支持,并且不能保护您免受并发/并行性引起的冲突。

标签: sql-server tsql sql-server-2012


【解决方案1】:

这不能保证有效,我相信 Phil Haack 会说。把这段代码扔掉。

可能的原因是并行性。该变量可能会被多个线程敲击。

奇怪的是,大约 19K 恰好有 12 个重复对象(我的机器上的处理器数量相同)。

这符合解释。

使用ROW_NUMBER 生成良好的保证工作ID:

update t
set ID = r
from (
 select *, row_number() over (order by something) r from T
) t

同样简单但理智。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-01
    • 1970-01-01
    • 2021-03-14
    • 2011-10-20
    • 1970-01-01
    • 2021-03-24
    • 2011-09-02
    • 1970-01-01
    相关资源
    最近更新 更多