web-dev-qa-db-fra.com

Pourquoi l'ajout d'une colonne NOT NULL avec une contrainte par défaut est-il instantané?

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

Lorsque j'exécute ce script de test, le ALTER avec UPDATE prend 6 secondes, ce qui est compréhensible.

Cependant, le ALTER avec le DEFAULT NOT NULL s'exécute instantanément, même sur une table beaucoup plus grande. Y a-t-il une explication sur la raison pour laquelle cela est instantané? Sur le disque physique, les données doivent encore être écrites sur toutes les lignes, n'est-ce pas?

J'ai essayé de regarder SET STATISTICS IO ON et le plan Query, mais ceux-ci ne semblent pas être disponibles pour les opérations DDL.

16
Akash

Oui, l'ajout d'une colonne avec NOT NULL et une valeur par défaut n'écrit pas réellement les valeurs dans toutes les lignes au moment de la modification, il ne s'agit donc plus d'une opération de taille de données. Lorsque vous sélectionnez dans le tableau, les colonnes sont réellement matérialisées à partir de sys.system_internals_partition_columns , ce qui empêche d'avoir à écrire toutes les valeurs (jusqu'à ce qu'elles soient modifiées). Notez que cela ne fonctionne pas pour tous les types de données et nécessite Enterprise Edition.

Remus Rusan explique cela plus en détail ici:

De plus, pour un ALTER au moins, nous ne pouvons toujours pas vous montrer de plan car SQL Server n'en produit pas, mais pour voir les E/S, vous pouvez utiliser SQL Sentry Plan Explorer . * Cette capture d'écran montre l'ajout d'une colonne, c5, "en ligne" comme décrit ci-dessus, puis d'une autre colonne, c6, "hors ligne" car les types LOB ne sont pas pris en charge. Vous pouvez voir que les E/S sont principalement exprimées en lecture plutôt qu'en écriture, mais ce qui est plus révélateur, c'est (invalide!) UPDATE associé à la modification hors ligne.

I/O for online vs. offline alter

Si vous n'avez pas Enterprise Edition, les deux instructions auront le UPDATE secondaire attaché (et les lectures associées). (Et si vous utilisez la version gratuite de Plan Explorer, qui n'obtient pas la pile complète d'appels de requête, vous ne verrez pas ce qui précède - vous verrez juste une arborescence d'instructions vide. Une version payante est requise pour voir la requête complète pile d'appel.)

Notez que SQL Server produira un plan estimé , mais ce n'est pas très utile. Du tout. Et le plan estimé pour un alter en ligne est identique au plan estimé pour un alter hors ligne.

Plan diagram for online alter

* Avertissement: je travaille pour SQL Sentry.

23
Aaron Bertrand