列をNOT NULLに変更すると、NULL値がない場合でも、SQL Serverはすべてのページにアクセスする必要があります。フィルファクターによっては、実際には多くのページ分割が発生する可能性があります。もちろん、触れられたすべてのページをログに記録する必要があり、多くのページで2つの変更をログに記録する必要がある可能性があるため、分割のために疑います。ただし、すべて1回のパスで行われるため、ログはすべての変更を考慮に入れる必要があります。そのため、キャンセルをクリックすると、元に戻す内容が正確にわかります。
例。シンプルなテーブル:
DROP TABLE dbo.floob;
GO
CREATE TABLE dbo.floob
(
id INT IDENTITY(1,1) NOT NULL PRIMARY KEY CLUSTERED,
bar INT NULL
);
INSERT dbo.floob(bar) SELECT NULL UNION ALL SELECT 4 UNION ALL SELECT NULL;
ALTER TABLE dbo.floob ADD CONSTRAINT df DEFAULT(0) FOR bar
それでは、ページの詳細を見てみましょう。まず、どのページとDB_IDを扱っているかを知る必要があります。私の場合、というデータベースを作成しましたがfoo
、DB_IDはたまたま5でした。
DBCC TRACEON(3604, -1);
DBCC IND('foo', 'dbo.floob', 1);
SELECT DB_ID();
出力は、159ページ(のDBCC IND
出力の唯一の行PageType = 1
)に興味があることを示しています。
次に、OPのシナリオをステップごとに選択するページの詳細を見てみましょう。
DBCC PAGE(5, 1, 159, 3);
UPDATE dbo.floob SET bar = 0 WHERE bar IS NULL;
DBCC PAGE(5, 1, 159, 3);
ALTER TABLE dbo.floob ALTER COLUMN bar INT NOT NULL;
DBCC PAGE(5, 1, 159, 3);
今、私はこれに対するすべての答えを持っているわけではありません。しかし、更新操作とNOT NULL制約の追加の両方が紛れもなくページに書き込みを行う一方で、後者はまったく異なる方法で書き込みを行うことは明らかです。ヌル値を許可する列をヌル値を許可しない列に交換することで、ビットをいじるのではなく、実際にレコードの構造を変更するようです。なぜそれをしなければならないのか、私にはよくわからない- ストレージエンジンチームにとって良い質問だと思う。SQL Server 2012はこれらのシナリオのいくつかをFWIWでより良く処理できると思いますが、徹底的なテストはまだ行っていません。
NOT NULL
メタデータ操作としてデフォルトで列を追加する機能を追加します。ドキュメントの「オンライン操作としてのNOT NULL列の追加」も参照してください。