Warum scheint ein UPDATE für eine Tabelle mit einem INSTEAD OF UPDATE-Trigger eine Clustered-Index-Einfügung sowie eine Clustered-Index-Aktualisierung durchzuführen?

10

Ich beginne mit einem sehr einfachen Beispiel: Zwei Tabellen, beide mit demselben Schema, gruppiert auf PK, von denen eine einen INSTEAD OF UPDATEAuslöser hat:

CREATE TABLE Standard
(
    PK  UNIQUEIDENTIFIER PRIMARY KEY CLUSTERED,
    V   INT NOT NULL
)
GO

CREATE TABLE InsteadOf
(
    PK  UNIQUEIDENTIFIER PRIMARY KEY CLUSTERED,
    V   INT NOT NULL
)
GO

INSERT Standard (PK, V) VALUES ('1E58B555-B073-471E-B576-4B09C8E18976', 0)
INSERT InsteadOf (PK, V) VALUES ('1E58B555-B073-471E-B576-4B09C8E18976', 0)
GO

CREATE TRIGGER TR_InsteadOf_Update ON InsteadOf INSTEAD OF UPDATE
AS
BEGIN
    DECLARE @PK UNIQUEIDENTIFIER
    DECLARE @V INT
    DECLARE @cursor CURSOR
    SET @cursor = CURSOR FOR SELECT PK, V FROM Inserted
    OPEN @cursor

    FETCH NEXT FROM @cursor INTO @PK, @V
    WHILE @@FETCH_STATUS = 0
    BEGIN
        UPDATE InsteadOf SET
            V = @V
        WHERE PK = @PK

        FETCH NEXT FROM @cursor INTO @PK, @V
    END
    CLOSE @cursor
    DEALLOCATE @cursor

END
GO

Wenn ich den Abfrageplan für eine Aktualisierung anhand der Standardtabelle ansehe, wird die erwartete Aktualisierung des verklumpten Index angezeigt:

UPDATE Standard SET
    V = 1
    WHERE PK = '1E58B555-B073-471E-B576-4B09C8E18976'

Geben Sie hier die Bildbeschreibung ein

Wenn ich jedoch mit dem Trigger eine ähnliche Aktualisierung für die Tabelle durchführe, erhalte ich eine scheinbar gruppierte Indexeinfügung sowie die Aktualisierung des gruppierten Index:

UPDATE InsteadOf SET
    V = 1
    WHERE PK = '1E58B555-B073-471E-B576-4B09C8E18976'

Geben Sie hier die Bildbeschreibung ein

Warum ist das? Ich kann die Clustered-Index-Aktualisierung sehen, die ich später in diesem Abfrageplan erwartet habe (Abfrage Nr. 4), aber warum erhalte ich diese zusätzliche Einfügung bei Abfrage Nr. 1?

Stusmith
quelle

Antworten:

10

Ein INSTEAD OFTrigger speichert eine Kopie der Zeilen, die in einer versteckten Arbeitstabelle * betroffen wären. Dies ist der angezeigte Clustered Index Insert. Der Trigger-Body liest aus dieser Arbeitstabelle * und alle Datenänderungen im Trigger verwenden den Operator 'normal' (Clustered Index Update in Ihrem Beispiel).


* Der Abfrageprozessor benennt die Arbeitstabelle intern um, wenn die vom Benutzer sichtbare Form des Ausführungsplans erstellt wird. Beim Schreiben wird es in die Zielbasis-Tabelle umbenannt, beim Lesen wird es umbenannt insertedoder deletedmehr oder weniger so, wie es die Leute in einem Trigger erwarten würden.

Weitere Informationen finden Sie in meinem Artikel Interessante Informationen zu STATT Auslösern .

Paul White 9
quelle