web-dev-qa-db-ja.com

デフォルトの制約を持つNOT NULL列を瞬時に追加するのはなぜですか?

CREATE TABLE TestTab (ID INT IDENTITY(1,1), st nvarchar(100))

INSERT INTO TestTab (st) values ('a')
INSERT INTO TestTab (st) values ('b')
INSERT INTO TestTab (st) values ('c')
INSERT INTO TestTab (st) values ('d')
INSERT INTO TestTab (st) values ('e')

INSERT INTO TestTab (st) SELECT TOP 10000 st from testtab
GO 30

ALTER TABLE TestTab ADD newcol nvarchar(10) DEFAULT 'newcol'
UPDATE TestTab SET newcol = 'newcol'  --6 sec
ALTER TABLE TestTab ADD newcol1 nvarchar(10) DEFAULT 'newcol1' NOT NULL

DROP TABLE TestTab

このテストスクリプトを実行すると、ALTERUPDATEは6秒かかり、理解できます。

ただし、ALTERDEFAULT NOT NULLを併用すると、非常に大きなテーブルでも瞬時に実行されます。なぜこれが瞬間的であるのかについての説明はありますか?物理ディスクでは、データをすべての行に書き込む必要がありますか?

SET STATISTICS IO ONとクエリプランを見てみましたが、これらはDDL操作で使用できないようです。

16
Akash

はい。NOTNULLとデフォルトの列を追加しても、実際には変更時にすべての行に値が書き込まれるわけではないため、データのサイズ操作ではなくなります。テーブルから選択すると、列は実際には sys.system_internals_partition_columns から実体化され、すべての値を(変更されるまで)書き込む必要がなくなります。これはすべてのデータ型で機能するわけではなく、Enterprise Editionが必要であることに注意してください。

Remus Rusanu がこれについて詳しく説明しています。

また、少なくともALTERの場合、SQL Serverは計画を生成しないため、計画を表示することはできませんが、I/Oを確認するには、 SQL Sentryを使用できますPlan Explorer 。*このスクリーンショットは、前述のように列c5、 "online"を追加してから、LOBタイプがサポートされていないため、別の列c6、 "offline"を追加することを示しています。 I/Oはほとんど書き込みではなく読み取りとして表現されていることがわかりますが、オフラインの変更に関連付けられている(無効!)UPDATEがよりわかります。

I/O for online vs. offline alter

Enterprise Editionがない場合は、両方のステートメントにセカンダリUPDATE(および関連する読み取り)がアタッチされます。 (そして、完全なクエリ呼び出しスタックを取得しない無料バージョンのプランエクスプローラーを使用する場合、上記は表示されません-空のステートメントツリーが表示されるだけです。完全なクエリを表示するには有料バージョンが必要です呼び出しスタック。)

SQL Serverは推定プランを生成しますが、あまり役に立ちません。全然。また、オンライン変更の推定計画は、オフライン変更の推定計画と同じです。

Plan diagram for online alter

*免責事項:私はSQLセントリーで働いています。

23
Aaron Bertrand