Pourquoi une mise à jour sur une table avec un déclencheur INSTEAD OF UPDATE semble-t-elle effectuer une insertion d'index cluster, ainsi qu'une mise à jour d'index cluster?

10

Je vais commencer par un exemple très simple: deux tables, toutes les deux avec le même schéma, clusterisées sur PK, mais dont l'une a un INSTEAD OF UPDATEdéclencheur:

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

Si j'affiche le plan de requête pour une mise à jour par rapport à la table standard, j'obtiens la mise à jour attendue de l'index sécurisé:

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

entrez la description de l'image ici

Cependant, si j'effectue une mise à jour similaire sur la table avec le déclencheur, j'obtiens ce qui semble être une insertion d'index en cluster, ainsi que la mise à jour de l'index en cluster:

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

entrez la description de l'image ici

Pourquoi est-ce? Je peux voir la mise à jour d'index cluster que j'attendais plus tard dans ce plan de requête (requête # 4), mais pourquoi est-ce que j'obtiens cet insert supplémentaire à la requête # 1?

stusmith
la source

Réponses:

10

Un INSTEAD OFdéclencheur stocke une copie des lignes qui seraient affectées dans une table de travail cachée *. Il s'agit de l'insertion d'index cluster que vous voyez. Le corps du déclencheur lit à partir de cette table de travail * et tout changement de données dans le déclencheur utilise l'opérateur «normal» (mise à jour d'index clusterisé dans votre exemple).


* Le processeur de requêtes renomme en interne la table de travail lors de la construction de la forme visible par l'utilisateur du plan d'exécution. Lors de l' écriture, il est renommé à la table de base cible, lors de la lecture, il est renommé insertedou deletedplus ou moins que les gens attendent de voir dans un déclencheur.

Pour plus de détails, consultez mon article Choses intéressantes sur les déclencheurs INSTEAD OF .

Paul White 9
la source