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

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.


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.


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.