将标识列从 INT 更改为 BIGINT

Fel*_*tan 11 sql-server sql-server-2008-r2 identity

我有一个带有标识列的表,它也是一个主键。目前,它有 5000 万行,身份列的最高值是 148,921,803。该表有很多DELETEs 并INSERTS在其上执行,因此价值很高。

我们要将数据类型从 更改INTBIGINT以准备添加更多行。请注意,没有对 PK 列的引用。

做到这一点的最佳方法是什么,停机时间最少?我有两个选择。

  1. 删除 PK 并更改列;或者
  2. 复制落重命名方法,描述在这里

小智 10

由于在标识列上定义了一个主键,您将无法直接更改此列。

您在问题中提到的两种方法都可以使用,停机时间取决于您的服务器的性能以及该表中的行数。

  1. 删除 PK 并更改列;或者

先放下PK

/****** Object: DROP Index [PK_DatabaseLog_DatabaseLogID]******/

ALTER TABLE [dbo].[TableName] DROP CONSTRAINT [PK_TableName_ID]
GO
Run Code Online (Sandbox Code Playgroud)

更改列

ALTER TABLE [dbo].[TableName] ALTER COLUMN [dbo.ID] BIGINT
Run Code Online (Sandbox Code Playgroud)

添加主键

/****** Object: ADD Index [PK_DatabaseLog_DatabaseLogID]******/
ALTER TABLE [dbo].[TableName] ADD  CONSTRAINT [PK_TableName_ID] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)
Run Code Online (Sandbox Code Playgroud)

这种方法通常不会花费太多时间。在我的环境中,在超过 500 万行的大表上需要花费几秒钟的时间。

  1. 复制-删除-重命名方法,如所述

您也可以使用这种方法。但是,对于这种方法,您需要比方法一更多的停机时间,因为您必须同步表。


Pau*_*ite 9

Aaron Bertrand 有一个关于这个主题的 4 部分系列,从:

最大限度地减少加宽 IDENTITY 列的影响 - 第 1 部分

如果您绝对需要迁移到bigint,必须最大限度地减少停机时间并有足够的时间进行规划,那么他在第 4 部分中记录的方法是:

在非常高的层次上,做法是创建一组影子表,其中所有插入都指向表的新副本(具有更大的数据类型),并且两组表的存在是透明的应用程序及其用户。

更详细地,亚伦说:

  1. 使用正确的数据类型创建表的卷影副本。
  2. 更改存储过程(或临时代码)以使用 bigint 作为参数。(这可能需要在参数列表之外进行修改,例如局部变量、临时表等,但这里并非如此。)
  3. 重命名旧表,并使用合并旧表和新表的名称创建视图。
    • 这些视图将具有而不是触发器来正确地将 DML 操作定向到适当的表,以便在迁移期间仍然可以修改数据。
    • 这还需要从任何索引视图中删除 SCHEMABINDING,现有视图在新表和旧表之间具有联合,以及依赖 SCOPE_IDENTITY() 的过程被修改。
  4. 将旧数据分块迁移到新表。
  5. 清理,包括:
    • 删除临时视图(这将删除 INSTEAD OF 触发器)。
    • 将新表重命名回原始名称。
    • 修复存储过程以恢复到 SCOPE_IDENTITY()。
    • 删除旧的,现在是空的表。
    • 将 SCHEMABINDING 放回索引视图并重新创建聚集索引。