4

我有几张表,有数百万行,有些表有数十亿行,其中一列是 int 现在我正在更改为 bigint。我尝试使用 SSMS 更改数据类型,但由于事务日志已满,几个小时后它失败了。

我采取的另一种方法是创建一个新列并开始将值从旧列批量更新到新列,通过将ROWCOUNT属性设置为 100000,它可以工作,但速度很慢,并且它要求完整的服务器内存。使用这种方法,可能需要几天时间才能完成,并且在生产中是不可接受的。

更改数据类型的快速\最佳方法是什么?源列不是标识列且重复,允许为空。该表在其他列上有索引,禁用索引会加快进程吗?添加 Begin Tran 和 Commit 会有帮助吗?

4

2 回答 2

7

我对 ALTER COLUMN 进行了测试,显示了进行更改所需的实际时间。结果表明,ALTER COLUMN不是瞬时的,所需时间呈线性增长。

RecordCt    Elapsed Mcs
----------- -----------
      10000      184019
     100000     1814181
    1000000    18410841

我的建议是按照你的建议批量处理。创建一个新列,并随着时间的推移使用ROWCOUNTWAITFOR的组合预填充该列。

对脚本进行编码,以便从表中读取 WAITFOR 值。这样,您可以在生产服务器开始陷入困境时即时修改 WAITFOR 值。您可以在非高峰时段缩短 WAITFOR。(您甚至可以使用 DMV 使您的 WAITFOR 值自动生成,但这肯定更复杂。)

这是一个复杂的更新,需要计划和大量的保姆。


这是 ALTER COLUMN 测试代码。

USE tempdb;
SET NOCOUNT ON;
GO
IF EXISTS (SELECT * FROM sys.tables WHERE [object_id] = OBJECT_ID('dbo.TestTable'))
    DROP TABLE dbo.TestTable;
GO
CREATE TABLE dbo.TestTable (
    ColID   int              IDENTITY,
    ColTest int              NULL,
    ColGuid uniqueidentifier DEFAULT NEWSEQUENTIALID()
);
GO

INSERT INTO dbo.TestTable DEFAULT VALUES;
GO 10000

UPDATE dbo.TestTable SET ColTest = ColID;
GO

DECLARE @t1 time(7) = SYSDATETIME();
DECLARE @t2 time(7);

ALTER TABLE dbo.TestTable ALTER COLUMN ColTest bigint NULL;

SET @t2 = SYSDATETIME();

SELECT
    MAX(ColID)              AS RecordCt,
    DATEDIFF(mcs, @t1, @t2) AS [Elapsed Mcs]
FROM dbo.TestTable;
于 2012-04-16T22:09:03.753 回答
0

一个简单的alter table <table> alter column <column> bigint null应该基本上没有时间。不会有任何转换问题或空检查 - 我不明白为什么这不会相对即时

如果您通过 GUI 执行此操作,它可能会尝试创建一个临时表,删除现有表,然后创建一个新表 - 绝对不要这样做

于 2012-04-16T20:58:34.213 回答