我有一个带有标识列的表,该列也是主键。当前,它有5000万行,标识列的最高值为148921803。该表具有很多DELETE
s并对其INSERTS
执行,因此值很高。
我们希望将数据类型从更改为INT
,BIGINT
以准备添加更多行。请注意,没有对PK列的引用。
用最少的停机时间来做到这一点的最佳方法是什么?我有两个选择。
- 放下PK并更改色谱柱;要么
- 复制落重命名方法,描述在这里:
我有一个带有标识列的表,该列也是主键。当前,它有5000万行,标识列的最高值为148921803。该表具有很多DELETE
s并对其INSERTS
执行,因此值很高。
我们希望将数据类型从更改为INT
,BIGINT
以准备添加更多行。请注意,没有对PK列的引用。
用最少的停机时间来做到这一点的最佳方法是什么?我有两个选择。
Answers:
由于在标识列中定义了主键,因此您将无法直接更改此列。
您在问题中提到的两种方法都可以使用,停机时间取决于服务器的运行方式以及该表中驻留的行数。
- 放下PK并更改色谱柱;要么
先掉PK
/****** Object: DROP Index [PK_DatabaseLog_DatabaseLogID]******/
ALTER TABLE [dbo].[TableName] DROP CONSTRAINT [PK_TableName_ID]
GO
更改列
ALTER TABLE [dbo].[TableName] ALTER COLUMN [dbo.ID] BIGINT
添加主键
/****** Object: ADD Index [PK_DatabaseLog_DatabaseLogID]******/
ALTER TABLE [dbo].[TableName] ADD CONSTRAINT [PK_TableName_ID] PRIMARY KEY CLUSTERED
(
[ID] ASC
)
这种方法通常不会花费很多时间。在我的环境中,在具有超过500万行的大表上需要花费几秒钟的时间。
- 复制-重命名方法,如所述
您也可以使用这种方法。但是,与同步方法相比,与同步方法相比,这种方法需要更多的停机时间,因为您必须同步表。
亚伦·伯特兰德(Aaron Bertrand)对此主题有4个系列,从以下开始:
如果您绝对需要迁移到bigint
,必须将停机时间降到最低,并且有足够的时间进行计划,那么他在第4部分中介绍的方法是:
在很高的级别上,方法是创建一组影子表,其中所有插入都定向到该表的新副本(具有较大的数据类型),并且两组表的存在是透明的对应用程序及其用户而言尽可能。
更详细地说,亚伦说:
- 使用正确的数据类型创建表的卷影副本。
- 更改存储过程(或临时代码)以将bigint用作参数。(这可能需要修改参数列表之外的参数,例如局部变量,临时表等,但是这里不是这种情况。)
- 重命名旧表,并使用合并新旧表的名称创建视图。
- 这些视图将具有触发器,而不是触发器,以将DML操作正确地定向到适当的表,以便仍可以在迁移期间修改数据。
- 这还要求从任何索引视图中删除SCHEMABINDING,在现有视图中使新表与旧表之间具有并集,并且依赖于SCOPE_IDENTITY()的过程将被修改。
- 批量将旧数据迁移到新表。
- 清理,包括:
- 删除临时视图(这将删除INSTEAD OF触发器)。
- 将新表重命名回原始名称。
- 修复存储过程以恢复为SCOPE_IDENTITY()。
- 删除旧的,现在为空的表。
- 将SCHEMABINDING重新放在索引视图上并重新创建聚簇索引。