MERGE usa tempdb?

12

Considere a seguinte consulta:

MERGE [Parameter] with (rowlock) AS target
    USING (SELECT @AreaId, @ParameterTypeId, @Value)
            AS source (AreaId, ParameterTypeId, Value)
    ON (target.AreaId = source.AreaId AND 
        target.ParameterTypeId = source.ParameterTypeId)
    WHEN MATCHED THEN 
        UPDATE SET target.Value = source.Value, @UpdatedId = target.Id
    WHEN NOT MATCHED THEN
        INSERT ([AreaId], [ParameterTypeId], [Value])
        VALUES (source.AreaId, source.ParameterTypeId, source.Value);

E / S de estatísticas fornece a seguinte saída:

Tabela 'ParameterType'. Contagem de varreduras 0, leituras lógicas 2, leituras físicas 0, leituras de leitura antecipada 0, leituras lógicas de lob 0, leituras físicas de lob 0, leituras físicas de lob 0, leituras de leitura antecipada de 0.
Tabela 'Área'. Contagem de varreduras 0, leituras lógicas 2, leituras físicas 0, leituras de leitura antecipada 0, leituras lógicas de lob 0, leituras físicas de lob 0, leituras físicas de lob 0, leituras de leitura antecipada de 0.
Tabela 'Parâmetro'. Contagem de varredura 1, leituras lógicas 4, leituras físicas 0, leituras de leitura antecipada 0, leituras lógicas de lob 0, leituras físicas de lob 0, leituras físicas de lob 0, leituras de leitura antecipada de lob 0.
Tabela 'Worktable'. Contagem de varreduras 1, leituras lógicas 0, leituras físicas 0, leituras de leitura antecipada 0, leituras lógicas de lob 0, leituras físicas de lob 0, leituras físicas de lob 0, leituras de leitura antecipada de lob 0.

A tabela de trabalho aparece na guia Mensagens, o que me faz pensar que o tempdb está sendo usado pelo MERGE .

Não estou vendo nada no plano de execução que indique a necessidade de tempdb

Será MERGEsempre usar tempdb?

Existe algo no BOL que explique esse comportamento?

Usar INSERTe UPDATEser mais rápido nessa situação?

Esquerda

insira a descrição da imagem aqui

Certo

insira a descrição da imagem aqui

Aqui está a estrutura da tabela

insira a descrição da imagem aqui

Craig Efrein
fonte
O carretel no plano é uma mesa de trabalho em tempdb. Parece estranho que ele esteja lá por uma única linha. Eu acho que pode estar lá para a proteção do Halloween.
Martin Smith
Eu vejo agora. Armazena os dados da entrada em uma tabela temporária para otimizar retrocessos.
Craig Efrein

Respostas:

8

(Expandindo meu comentário sobre a pergunta.)

Sem uma restrição exclusiva na combinação de AreaIde ParameterTypeId, o código fornecido é quebrado porque @UpdatedId = target.Idapenas registrará uma única linhaId .

A menos que você diga, o SQL Server não pode saber implicitamente os possíveis estados dos dados. A restrição deve ser imposta ou, se várias linhas forem válidas , o código precisará ser alterado para usar um mecanismo diferente para gerar os Idvalores.

Devido à possibilidade de o operador de varredura encontrar várias linhas correspondentes, a consulta deve colocar em spool todas as correspondências para proteção de Halloween. Conforme indicado nos comentários, a restrição é válida, portanto, adicioná-la não apenas mudará o plano de uma varredura para uma busca, mas também eliminará a necessidade do spool de tabela, pois o SQL Server saberá que haverá 0 ou 0 1 linhas retornadas do operador de busca.

Jon Seigel
fonte
6

Se a atualização puder alterar a posição da linha no índice verificado pela atualização, o SQL Server precisará se proteger do Problema do Dia das Bruxas . Para isso, o SQL Server geralmente insere um spool de tabela ansioso no plano de execução logo após a verificação do índice. Esse operador basicamente cria uma cópia das linhas em questão e usa tempdb para isso.

A parte de atualização da instrução MERGE precisa seguir as mesmas regras e também usa um spool de tabela na maioria dos casos em que a Proteção de Halloween é necessária.

Embora eu não possa dizer se esse é o caso da sua consulta, como não conheço as definições de índice, é mais provável que isso esteja acontecendo aqui.

Sebastian Meine
fonte