【问题标题】:SQL Column ID value jumps 10000 timesSQL Column ID值跳跃10000次
【发布时间】:2020-04-10 12:01:43
【问题描述】:

ID列索引跳转10000次。

例如:

来自索引

  • 5 转到10006

  • 然后继续100071000810009

  • 然后转到 20003 , 20004 ....

如何修复 ID 值并像以前一样重新排列它们?

我也找到了一些关于 Reseed 功能的东西,但我不知道它是什么以及如何使用它?

【问题讨论】:

  • 请提供一些关于表格中插入的信息。
  • 这是一个已知的有意功能,通常在(不正确的)关机后发生。 IDENTITY 是一个始终递增的任意数字,仅此而已。它的实际值除了大于先前的值之外没有任何意义,因此(与唯一约束一起)是 Primary Ket 的良好候选者。你不应该“关心”它的实际价值。
  • 如果你真的想要一个序列号,那么使用SEQUENCEdocs.microsoft.com/en-us/sql/t-sql/statements/…
  • 真的需要序号吗?

标签: sql sql-server indexing primary-key


【解决方案1】:

我假设您使用的是标识列:

ID INT NOT NULL IDENTITY(1,1)

无法保证这将保持顺序。当它第一次变得更加明显时很烦人(它似乎没有在旧版本的 SQL Server 中发生,但显然可能发生)但也总是设计使然。当 2012 (?) 发布时,跳过变得非常明显。你现在应该使用 SEQUENCE 我相信如果需要保持稳定的序列 - 例如发票号码:

https://dba.stackexchange.com/questions/62151/what-could-cause-an-auto-increment-primary-key-to-skip-numbers

https://docs.microsoft.com/en-us/sql/t-sql/statements/create-sequence-transact-sql?view=sql-server-ver15

如果您执行 INSERT 并且它失败,它也可能会出现跳过,但这通常只会跳过 1。这种情况总是会发生,而且是设计使然——你需要重新植入你的身份来克服这个问题。比如:

DBCC CHECKIDENT ("dbo.MyTable", RESEED, 10)

如果不发生其他跳过,则将下一个标识号设为 11。

编辑: 关于重新对齐现有条目,我不是数据库专家,但前几天我确实在一张桌子上使用了一种相当基本的方法 - 但它只是一张小桌子 - 可能有更好的方法来做到这一点:

BEGIN TRAN

--CREATE TEMP TABLE
DECLARE @Tooltip TABLE
(
    [TooltipId] INT NOT NULL,
    [TooltipKey] NVARCHAR(100) NOT NULL,
    [Name] NVARCHAR(255) NOT NULL
)

--INSERT EXISTING INTO TEMP TABLE
INSERT INTO @Tooltip (TooltipKey, Name )
SELECT TooltipKey, Name
FROM dbo.Tooltip
ORDER BY TooltipId


--CLEAR ACTUAL TABLE
TRUNCATE TABLE dbo.Tooltip

--RESET IDENTITY TO 1
DBCC CHECKIDENT ("dbo.Tooltip", RESEED, 1)

--REINSERT FROM TEMP TABLE INTO ACTUAL TABLE
INSERT INTO dbo.Tooltip (TooltipKey, Name )
SELECT TooltipKey, Name
FROM @Tooltip
ORDER BY TooltipId

--TEST OUTPUT
SELECT * FROM dbo.Tooltip

--DO THIS FOR TESTING
ROLLBACK TRAN

--DO THIS WHEN YOU'RE CERTAIN YOU WANT TO PERFORM THE ACTION
--COMMIT TRAN

请记住,如果您有外键或其他引用,则截断将不起作用,您将不得不做一些更复杂的事情。特别是如果您有引用现有错误 ID 的外键

【讨论】:

  • 如何从 Management Studio 中重新设置 ID 列?
  • 您能否解释一下 DBCC CHECKIDENT ("dbo.MyTable", RESEED, 10) 命令,它的含义及其组成部分?提前谢谢你
  • 另外,我怎样才能修复所有的 ID 值并从 1 ,2 ,3 ,4 .... 重新排列它们。
  • DBCC CHECKIDENT 代码将为该列重新设置种子 - 因此,如果您需要将其设置为下一个数字为 6,请执行 DBCC CHECKIDENT ("dbo.MyTable", RESEED, 6)
【解决方案2】:

这不是问题。这是 SQL Server 的一项性能特性。

SQL Server 旨在处理许多并发事务——想想每秒数十或数百个插入。它可以在具有多个处理器的系统上执行此操作。

在这样的环境中,“只加 1”到最大值会产生很多开销——所有不同的处理器都必须就最大值达成一致。这涉及事务的复杂锁定或排序——这会减慢速度。

为了防止性能瓶颈,SQL Server 有时会预先分配标识值。如果不使用数字,这可能会导致空白。

如果您不喜欢此功能,您可以通过使用序列和触发器来分配值来解决它。请注意,替代方法会对性能产生影响。

【讨论】:

    【解决方案3】:

    您是否进行过大量删除操作?

    删除不会重置标识,因此如果您有 1-10000 行,然后将它们全部删除,那么当您添加新行时,标识仍会从 10001 继续。

    截断会重置身份,但总是删除所有行而不记录。

    您也可以使用 reseed 函数来重置身份,但在这种情况下不会有帮助,因为您会慢慢增加回现有数据使用的 id。

    【讨论】:

    • 感谢您的回答,但我没有删除任何内容,如何重新设置 ID 列?
    • 要重新设置种子的函数将是“DBCC CHECKIDENT ('[TestTable]', RESEED, 0)”。但是不要这样做 - 您的表已经有数据。其他答案已经涵盖了身份差距的其他原因。如果编号很重要,请使用序列数据类型。
    猜你喜欢
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多