Wir haben eine Tabelle mit 2.3B Zeilen. Wir möchten eine Spalte von NOT NULL in NULL ändern. Die Spalte ist in einem Index enthalten (nicht im Clustered- oder PK-Index). Der Datentyp ändert sich nicht (es ist ein INT). Nur die Nichtigkeit. Die Aussage ist wie folgt:
Alter Table dbo.Workflow Alter Column LineId Int NULL
Der Vorgang dauert mehr als 10 Minuten, bevor er beendet wird (wir haben ihn noch nicht einmal vollständig ausgeführt, da es sich um einen blockierenden Vorgang handelt, der zu lange gedauert hat). Wir werden die Tabelle wahrscheinlich auf einen Entwickler-Server kopieren und testen, wie lange es tatsächlich dauert. Aber ich bin neugierig, ob jemand weiß, was SQL Server unter der Haube tut, wenn es von NOT NULL nach NULL konvertiert? Müssen betroffene Indizes auch neu erstellt werden? Der generierte Abfrageplan zeigt nicht an, was gerade passiert.
Die betreffende Tabelle ist gruppiert (kein Heap).
quelle
Antworten:
Wie von @Souplex in den Kommentaren angedeutet, könnte eine mögliche Erklärung darin bestehen, ob diese Spalte die erste
NULL
verfügbare Spalte im nicht gruppierten Index ist, an dem sie beteiligt ist.Für das folgende Setup
sys.dm_db_index_physical_stats zeigt, dass der nicht gruppierte Index
ix
248 Blattseiten und eine einzelne Stammseite hat.Eine typische Zeile in einer Indexblattseite sieht wie folgt aus
Und auf der Root-Seite
Dann rennen ...
Ist zurückgekommen
Wenn Sie das Indexblatt noch einmal überprüfen, sehen die Zeilen nun so aus
und die Zeilen in den oberen Seiten wie unten.
Jede Zeile wurde aktualisiert und enthält jetzt zwei Bytes für die Spaltenanzahl sowie ein weiteres Byte für die NULL_BITMAP.
Aufgrund der zusätzlichen Zeilenbreite hat der nicht gruppierte Index jetzt 285 Blattseiten und jetzt zwei Seiten auf Zwischenebene zusammen mit der Stammseite.
Der Ausführungsplan für die
sieht wie folgt aus
Dadurch wird eine brandneue Kopie des Index erstellt, anstatt den vorhandenen zu aktualisieren und die Seiten zu teilen.
quelle
Es wird definitiv den nicht gruppierten Index neu erstellen und nicht nur Metadaten aktualisieren. Dies wurde in SQL 2014 getestet und sollte nicht auf einem Produktionssystem getestet werden:
Und jetzt zum spaßigen Teil:
Dadurch erhalten wir die Datenbankseiten, auf denen die Tabelle und der nicht gruppierte Index gespeichert sind.
Suchen Sie nach dem
PagePID
WertIndexID
2 undPageType
2 und gehen Sie dann wie folgt vor:und dann:
Beachten Sie, dass der Header eine Null-Bitmap enthält:
Nun lass uns machen:
Wenn Sie wirklich ungeduldig sind, können Sie versuchen, den
dbcc page
Befehl erneut auszuführen , aber er schlägt fehl. Überprüfen Sie die Zuordnung also erneut mitDBCC IND (0, z, -1)
. Die Seite wird sich wie von Zauberhand bewegt haben.Das Ändern der Nullfähigkeit einer Spalte wirkt sich also auf die Speicherung von nicht gruppierten Indizes aus, die diese Spalte abdecken, da die Metadaten aktualisiert werden müssen und Sie die Indizes anschließend nicht neu erstellen müssen.
Viele
ALTER TABLE ... ALTER COLUMN ...
Vorgänge könnenONLINE
ab SQL Server 2016 ausgeführt werden, aber:quelle