Was passiert mit einem nicht gruppierten Index, wenn die enthaltene Spalte mithilfe der Update-Anweisung aktualisiert wird?

7

Frage zum nicht gruppierten Index mit enthaltenen Spalten (DB - MS SQL Server). Ich habe den Blog Optimized Non-Clustered Index Maintenance gelesen, der Informationen zu Abfrageplänen enthält, wenn Aktualisierungsanweisungen ausgeführt werden und Clustered Index und Non Clustered Index für die Tabelle definiert sind.
Ich habe Fragen zu nicht gruppierten Indizes mit eingeschlossenen Spalten. Ich beziehe mich auf dasselbe Beispiel von Blogger

CREATE TABLE T (PK INT, A INT, B INT, C INT, D INT, E INT)
CREATE UNIQUE CLUSTERED INDEX TPK ON T(PK)

CREATE INDEX TB ON T(B)
CREATE INDEX TCD ON T(C,D)
CREATE INDEX TE ON T(E)

- Dies ist ein neuer nicht gruppierter Index mit enthaltenen Spalten

CREATE INDEX TF ON T(E) INCLUDE(A)


INSERT T VALUES(0, 10, 20, 30, 40, 50)

UPDATE T SET A = 19

Wenn kein Index-TF definiert ist, wird nur eine Aktualisierung des Clustered-Index durchgeführt, und es werden keine nicht gruppierten Index-Einfüge- und Löschvorgänge ausgeführt. Aber was passiert, wenn TF definiert ist?

Delta
quelle

Antworten:

4

Der Blog-Beitrag, auf den Sie verweisen, gibt auch an, wie Sie dies selbst hätten beantworten können.

Wenn Sie ausführen

SET SHOWPLAN_TEXT ON;
GO
UPDATE T SET A = 19;

Der Plan sieht aus wie

  |--Clustered Index Update(OBJECT:([AdventureWorks2008].[dbo].[T].[TPK]), OBJECT:([AdventureWorks2008].[dbo].[T].[TF]), SET:([AdventureWorks2008].[dbo].[T].[A] = [@1]))
       |--Compute Scalar(DEFINE:([Expr1009]=[Expr1009]))
            |--Compute Scalar(DEFINE:([Expr1009]=CASE WHEN CASE WHEN [AdventureWorks2008].[dbo].[T].[A] = [@1] THEN (1) ELSE (0) END THEN (0) ELSE (1) END))
                 |--Top(ROWCOUNT est 0)
                      |--Index Scan(OBJECT:([AdventureWorks2008].[dbo].[T].[TF]), ORDERED FORWARD)

Anzeigen eines pro Zeile / schmalen Plans, in dem der Index TFals eines der aktualisierten Objekte aufgeführt ist.

Martin Smith
quelle
Nach dem Ausführen der Anweisung "update T set A = 20" wird leaf_update_count anstelle von leaf_insert_count geändert. Dies bedeutet, dass bei einer Aktualisierung der eingeschlossenen Spalte ein nicht gruppierter Blattknoten aktualisiert wird. Es wird kein Lösch- und Einfügevorgang ausgeführt. index_id leaf_insert_count leaf_update_count 5 0 1
Delta
@ Delta - So TFhat Indexid von 5 und seine leaf_update_count = 1(das war als Antwort auf frühere Version des Kommentars). Und ja, das hätte ich für eine enthaltene Kolumne erwartet. Das Löschen / Einfügen erfolgt im Allgemeinen, wenn Sie eine Schlüsselspalte aktualisieren, da sie dann möglicherweise verschoben werden muss. zB versuchenUPDATE T SET E = 25
Martin Smith
Ja 5 ist die Index-ID für TF und dessen leaf_update_count = 1. Wenn ich den Wert leaf_delete_count und non_leaf_delete_count für die Tabelle abgefragt habe, haben diese beiden Spalten 0 Werte. Es ist schwer zu verstehen, warum nur die Anzahl der Einfügungen aktualisiert wird, nicht die Anzahl der Löschvorgänge.
Delta
@ Delta - Schau dir an leaf_ghost_count. Aufzeichnungen werden zuerst als Geister markiert und später bereinigt.
Martin Smith
Sie meinen, delete_count enthält niemals gelöschte Zählungen, wenn Ghosts diese Werte enthalten und sie später auch bereinigt werden?
Delta
4

Genau wie beim Aktualisieren eines Werts in einem Index, der auf Blatt- und Nichtblattseiten gespeichert ist, werden alle diese Seiten mit dem neuen Wert aktualisiert. Spalten, die nur über include auf Blattebene gespeichert werden, werden aktualisiert, wenn Sie Werte aktualisieren. Dies kann auch zu Spage Splits führen.

Grant Fritchey
quelle
2

Wenn TF definiert ist, muss es aktualisiert werden. Dies liegt daran, dass der Wert von A auf der TF-Blattebene enthalten ist. Eine Aktualisierung in Spalte A muss diesen Wert im Index TF widerspiegeln.

Dies ist der Grund, warum Sie einen Include-Index TF haben, damit Sie nicht nach A suchen müssen, wenn Sie nur die Spalten E oder A benötigen.

Stanley Johns
quelle