Sql-Server

這個 ALTER TABLE 語句需要多長時間?

  • April 18, 2018
Alter TABLE [XXX] Alter column [YYY] [varchar](max) NULL

認為

  • 有45GB數據空間和2GB索引空間;
  • 該表中大約有 300 萬行;
  • YYY 列varchar(8000)現在可以更新(可寫)。
  • 該表有大約 30 個其他列。
  • 這台機器上有大約3000G來自其他數據庫和表的數據。

其他一些資訊:

  • 99.99% 的行在NULLvarchar(8000)
  • Web 應用程序可能每分鐘點擊該表 5 次;
  • 硬體為企業級(8 核 CPU 和 256GB RAM)。
  • 這台機器上還有其他的表和數據庫,大約3000GB的數據。

相關@@VERSION細節:

Microsoft SQL Server 2014 - 12.0.4422.0 (X64)
企業版(64 位)

沒有人可以確定或準確地告訴您此操作將在您的系統上花費多長時間。但是,我建議更改的影響可能比您想像的要小。我設置了一個快速測試來比較從int->bigint和從varchar(8000)->更改表格varchar(max)。首先,兩個簡單的表:

CREATE TABLE dbo.t0(a int primary key, b int);
GO
CREATE TABLE dbo.t1(a int primary key, b varchar(8000));
GO

現在,插入至少一個非 NULL 值,然後插入超過 500 萬行(在我的系統上;YMMV):

INSERT dbo.t0 VALUES(0,1);
INSERT dbo.t0 SELECT rn, NULL FROM 
( SELECT rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
 FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
) AS x;
GO -- 5,299,204 rows for me

INSERT dbo.t1 VALUES(0,'what');
INSERT dbo.t1 SELECT rn, NULL FROM 
( SELECT rn = ROW_NUMBER() OVER (ORDER BY s1.[object_id])
 FROM sys.all_objects AS s1 CROSS JOIN sys.all_objects AS s2
) AS x;
GO -- 5,299,204 rows for me

然後我測試了ALTER更改,啟用了統計 I/O:

SET STATISTICS IO ON;
GO
ALTER TABLE dbo.t0 ALTER COLUMN b bigint NULL; 
GO -- 9 seconds, 122,506 reads
SET STATISTICS IO OFF;

這在 9 秒內完成,需要 122,506 次讀取。

SET STATISTICS IO ON;
GO
ALTER TABLE dbo.t1 ALTER COLUMN b varchar(max) NULL; 
GO -- 5 seconds, 8,562 logical reads
SET STATISTICS IO OFF;

這在 5 秒內完成,只需要 8,562 次讀取。

因此,雖然這兩項操作都沒有線上發生,並且您的實際結果可能會因硬體和表結構而異,但這是在 MacBook 上的低級 Windows VM 上,所以我希望您的時間會比這更好。

我還測試了在可空列中填充的更多數據。刪除表,重新創建並重新填充上述腳本,然後執行它以將某些內容放入 100,000 行中:

;WITH x AS (SELECT TOP (100000) a,b FROM dbo.t1 ORDER BY NEWID())
UPDATE x SET b = a;
GO
;WITH x AS (SELECT TOP (100000) a,b FROM dbo.t1 ORDER BY NEWID())
UPDATE x SET b = REPLICATE(RTRIM(a), 1000);
GO

這比隨後的 s 花費ALTER時間更長(超過 3 分鐘)。第一個ALTER仍然需要 9 秒,但第二個需要 17 秒,這僅僅是因為讀取次數猛增(達到 189,854)。這類似於如果您在此表中有 30 個其他列會發生的情況。我仍然認為 17 秒對於這裡實際發生的事情來說是相當不錯的,而且這與企業級環境相去甚遠。

正如 Paul 指出的那樣,從 SQL Server 2016 開始,您可以線上實現這一點,但存在限制和限制。有關更多資訊,請參閱文件

ALTER TABLE dbo.t1 ALTER COLUMN b varchar(max) NULL WITH (ONLINE = ON);

但是,此選項在 SQL Server 2014 中不可用。

使這種情況在網上發生的一種方法是簡單地將該列移動到一個單獨的相關表中。這裡有一些你如何切換的複雜性,它可能會影響一堆程式碼,但你可以用視圖解決大多數問題(至少是暫時的)。

引用自:https://dba.stackexchange.com/questions/204302