INSERIR diferença de desempenho entre tabelas temporárias e variáveis ​​de tabela

12

Eu tenho o seguinte problema no SQL Server 2005: tentar inserir algumas linhas em uma variável da tabela leva muito tempo em comparação com a mesma inserção usando uma tabela temporária.

Este é o código para inserir na variável da tabela

DECLARE @Data TABLE(...)
INSERT INTO @DATA( ... )
SELECT ..
FROM ...

Este é o código para inserir na tabela temporária

CREATE #Data TABLE(...)
INSERT INTO #DATA( ... )
SELECT ..
FROM ...
DROP TABLE #Data

A tabela temporária não possui chaves ou índices, a parte de seleção é a mesma entre as 2 consultas e o número de resultados retornados pela seleção é de ~ 10000 linhas. O tempo necessário para executar a seleção sozinho é de ~ 10 segundos.

A versão da tabela temporária leva até 10 segundos para ser executada; tive que parar a versão da variável da tabela após 5 minutos.

Eu tenho que usar uma variável de tabela porque a consulta faz parte de uma função de valor da tabela, que não permite o acesso à tabela temporária.

Plano de execução para a versão da variável de tabela Plano de execução

Plano de execução para a versão da tabela temporária Plano de execução

munir
fonte

Respostas:

8

A diferença óbvia entre os dois planos é que o mais rápido é paralelo e o mais lento, o serial.

Essa é uma das limitações dos planos inseridos nas variáveis ​​da tabela. Como mencionado nos comentários (e parece que teve o efeito desejado), você pode tentar fazer

INSERT INTO @DATA ( ... ) 
EXEC('SELECT .. FROM ...')

para ver se isso contorna a limitação.

Martin Smith
fonte
Foi uma ótima sugestão, embora eu pensei que você não poderia usar EXECem uma função .... acho que estava errado
Lamak
1
@Lamak - Doh! Você não pode, então isso não funcionará para o OP. Invalid use of a side-effecting operator 'INSERT EXEC' within a function.. A OPENQUERYsolução alternativa pode funcionar.
Martin Smith
Ah, é bom saber, obrigado pelo esclarecimento
Lamak
2
Como regra geral, você não deseja usar variáveis ​​de tabela se desejar obter um conjunto de dados grande retornado. As tabelas temporárias são geralmente mais rápidas neste caso.
HLGEM
1
@ munun, então não use uma função com valor de tabela. Se você deseja um melhor conselho, poste exatamente o que está fazendo.
HLGEM
-1

Às vezes, as variáveis ​​da tabela são mais lentas porque não há estatísticas nas variáveis ​​da tabela e, portanto, o otimizador sempre assume apenas um registro.

No entanto, não posso garantir que esse seja o caso aqui, você deverá examinar as informações de "linhas estimadas" no plano de consulta da variável de tabela.

yoel halb
fonte
Como isso afetaria uma inserção em uma variável de tabela?
Martin Smith
É o que parece estar acontecendo, como você pode ver que não há apenas uma diferença entre junções paralelas e seriais, mas também entre junções hash e loop aninhadas, aparentemente o otimizador assume que, uma vez que a variável da tabela mantém um registro em mente, o resultado da consulta também será um registro. Mais uma vez, a única maneira de provar isso seria ver as estatísticas reais de cada parte da consulta, mas o fato é que todas as consultas que envolvem variáveis ​​de tabela acabam com junções de loop e processamento serial. então eu coisa que é justo a suspeitar-lo aqui
halb yoel