私の例は、数千万行ずつテーブルに新しい列を追加し、長時間ロックを実行せずにデフォルト値で埋める方法です
USE [MyDB]
GO
ALTER TABLE [dbo].[Customer] ADD [CustomerTypeId] TINYINT NULL
GO
ALTER TABLE [dbo].[Customer] ADD CONSTRAINT [DF_Customer_CustomerTypeId] DEFAULT 1 FOR [CustomerTypeId]
GO
DECLARE @batchSize bigint = 5000
,@rowcount int
,@MaxID int;
SET @rowcount = 1
SET @MaxID = 0
WHILE @rowcount > 0
BEGIN
;WITH upd as (
SELECT TOP (@batchSize)
[ID]
,[CustomerTypeId]
FROM [dbo].[Customer] (NOLOCK)
WHERE [CustomerTypeId] IS NULL
AND [ID] > @MaxID
ORDER BY [ID])
UPDATE upd
SET [CustomerTypeId] = 1
,@MaxID = CASE WHEN [ID] > @MaxID THEN [ID] ELSE @MaxID END
SET @rowcount = @@ROWCOUNT
WAITFOR DELAY '00:00:01'
END;
ALTER TABLE [dbo].[Customer] ALTER COLUMN [CustomerTypeId] TINYINT NOT NULL;
GO
ALTER TABLE [dbo].[Customer] ADD [CustomerTypeId] TINYINT NULL
メタデータのみを変更し (Sch-M ロック)、ロック時間はテーブル内の行数に依存しません
その後、デフォルト値で新しい列を少しずつ (5000 行) 埋めます。テーブルを積極的にブロックしないように、各サイクルの後に 1 秒待ちます。クラスター化された主キーとして int 列「ID」があります
最後に、すべての新しい列がいっぱいになったら、それを NOT NULL に変更します