Por que um UPDATE em uma tabela com um gatilho INSTEAD OF UPDATE parece fazer uma inserção de índice em cluster, bem como uma atualização de índice em cluster?

10

Começarei com um exemplo muito simples: duas tabelas, ambas com o mesmo esquema, agrupadas em PK, mas uma das quais possui um INSTEAD OF UPDATEgatilho:

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

Se eu visualizar o plano de consulta para uma atualização na tabela padrão, recebo a atualização esperada do índice protegido:

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

insira a descrição da imagem aqui

No entanto, se eu executar uma atualização semelhante na tabela com o gatilho, obtenho o que parece ser uma inserção de índice em cluster, bem como a atualização de índice em cluster:

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

insira a descrição da imagem aqui

Por que é isso? Posso ver a atualização do índice em cluster que eu esperava mais adiante neste plano de consulta (consulta 4), mas por que obtenho essa inserção extra na consulta 1?

stusmith
fonte

Respostas:

10

Um INSTEAD OFacionador armazena uma cópia das linhas que seriam afetadas em uma tabela de trabalho oculta *. Esta é a inserção de índice clusterizado que você vê. O corpo do acionador lê essa tabela de trabalho * e quaisquer alterações de dados no acionador usam o operador 'normal' (Atualização de Índice em Cluster no seu exemplo).


* O processador de consultas renomeia internamente a tabela de trabalho ao construir a forma visível do usuário do plano de execução. Ao gravá-lo, ele é renomeado para a tabela base de destino; ao ler, é renomeado como insertedou deletedmais ou menos como as pessoas esperariam ver em um gatilho.

Para mais detalhes, consulte o meu artigo Coisas interessantes sobre os gatilhos INSTEAD OF .

Paul White 9
fonte