Estou aprendendo mais detalhes na variável de tabela. Ele diz que as tabelas temporárias estão sempre no disco e as variáveis da tabela estão na memória, ou seja, o desempenho da variável da tabela é melhor que a tabela temporária porque a variável da tabela usa menos operações de E / S do que a tabela temporária.
Mas, às vezes, se houver muitos registros em uma variável da tabela que não possam estar contidos na memória, a variável da tabela será colocada em disco como a tabela temporária.
Mas não sei o que são "muitos registros". 100.000 registros? ou 1000.000 registros? Como posso saber se uma variável de tabela que estou usando está na memória ou no disco? Existe alguma função ou ferramenta no SQL Server 2005 para medir a escala da variável da tabela ou me avisar quando a variável da tabela é colocada no disco a partir da memória?
tempDB
- que "na memória" é um mito. Além disso: as variáveis de tabela sempre serão consideradas pelo otimizador de consultas como contendo exatamente uma linha - se você tiver muito mais, isso pode levar a planos de execução muito ruins.tempdb
(mas também pode ser inteiramente em memória)Respostas:
Sua pergunta mostra que você sucumbiu a alguns dos equívocos comuns sobre variáveis de tabela e tabelas temporárias.
Eu escrevi uma resposta bastante extensa no site do DBA, analisando as diferenças entre os dois tipos de objetos. Isso também aborda sua pergunta sobre disco x memória (não vi nenhuma diferença significativa de comportamento entre os dois).
Em relação à pergunta no título, porém, sobre quando usar uma variável de tabela versus uma tabela temporária local, você nem sempre tem uma opção. Em funções, por exemplo, só é possível usar uma variável de tabela e, se você precisar gravar na tabela em um escopo filho, somente uma
#temp
tabela o fará (parâmetros com valor de tabela permitem acesso somente leitura ).Onde você pode escolher, algumas sugestões estão abaixo (embora o método mais confiável seja simplesmente testar os dois com sua carga de trabalho específica).
Se você precisar de um índice que não possa ser criado em uma variável de tabela, é claro que precisará de uma
#temporary
tabela. Os detalhes disso dependem da versão, no entanto. Para o SQL Server 2012 e abaixo os únicos índices que poderiam ser criados na tabela variáveis foram aqueles implicitamente criados através de umaUNIQUE
ouPRIMARY KEY
restrição. O SQL Server 2014 introduziu a sintaxe de índice embutido para um subconjunto das opções disponíveis emCREATE INDEX
. Isso foi estendido desde então para permitir condições de índice filtradas. NoINCLUDE
entanto, ainda não é possível criar índices com colunas -d ou columnstorestore.Se você incluir e excluir repetidamente grandes números de linhas da tabela, use uma
#temporary
tabela. Isso suportaTRUNCATE
(que é mais eficiente do queDELETE
para tabelas grandes) e inserções adicionais subsequentes após aTRUNCATE
podem ter um desempenho melhor do que as que seguem aDELETE
conforme ilustrado aqui .#temporary
tabela. Isso suporta a criação de estatísticas que permitem que o plano seja recompilado dinamicamente de acordo com os dados (embora para tabelas temporárias em cache em procedimentos armazenados, o comportamento da recompilação precise ser entendido separadamente).SELECT
declaração potencialmente cara , considere que o uso de uma variável de tabela bloqueará a possibilidade disso usando um plano paralelo.#temp
tabela dentro de uma transação de usuário, os bloqueios podem ser mantidos por mais tempo do que para as variáveis da tabela (potencialmente até o final da transação versus o final da instrução, dependendo do tipo de nível de bloqueio e isolamento) e também podem impedir o truncamento dotempdb
log de transações até o a transação do usuário termina. Portanto, isso pode favorecer o uso de variáveis de tabela.#temporary
tabelas. Bob Ward ressalta em suatempdb
apresentação que isso pode causar contenção adicional nas tabelas do sistema em condições de alta simultaneidade. Além disso, ao lidar com pequenas quantidades de dados, isso pode fazer uma diferença mensurável no desempenho .Efeitos do compartilhamento de conjunto de linhas
fonte
id
e o uso deOPTION (RECOMPILE)
provavelmente seriam boas para isso - mas teste as duas.Use uma variável de tabela para uma quantidade muito pequena de dados (milhares de bytes)
Use uma tabela temporária para muitos dados
Outra maneira de pensar sobre isso: se você acha que pode se beneficiar de um índice, estatísticas automatizadas ou qualquer benefício do otimizador de SQL, seu conjunto de dados provavelmente é muito grande para uma variável de tabela.
No meu exemplo, eu só queria colocar cerca de 20 linhas em um formato e modificá-las como um grupo, antes de usá-las para UPDATE / INSERT uma tabela permanente. Portanto, uma variável de tabela é perfeita.
Mas também estou executando o SQL para preencher milhares de linhas por vez e, definitivamente, posso dizer que as tabelas temporárias têm um desempenho muito melhor que as variáveis da tabela.
Isso não é diferente de como as CTEs são uma preocupação por um motivo de tamanho semelhante - se os dados na CTE forem muito pequenos, acho que a CTE tem um desempenho tão bom ou melhor do que o otimizador, mas se for muito grande, isso te machuca muito.
Meu entendimento é baseado principalmente em http://www.developerfusion.com/article/84397/table-variables-v-temporary-tables-in-sql-server/ , que possui muito mais detalhes.
fonte
A Microsoft diz aqui
fonte
Eu concordo totalmente com Abacus (desculpe - não tenho pontos suficientes para comentar).
Além disso, lembre-se de que não se trata necessariamente de quantos registros você possui, mas do tamanho dos seus registros.
Por exemplo, você considerou a diferença de desempenho entre 1.000 registros com 50 colunas cada vs 100.000 registros com apenas 5 colunas cada?
Por fim, talvez você esteja consultando / armazenando mais dados do que precisa? Aqui está uma boa leitura sobre estratégias de otimização de SQL . Limite a quantidade de dados que você está obtendo, especialmente se você não estiver usando tudo (alguns programadores SQL ficam preguiçosos e apenas selecionam tudo, mesmo que usem apenas um pequeno subconjunto). Não esqueça que o analisador de consultas SQL também pode se tornar seu melhor amigo.
fonte
A tabela variável está disponível apenas para a sessão atual. Por exemplo, se você precisar de
EXEC
outro procedimento armazenado na atual, precisará passar pela tabela, pois éTable Valued Parameter
claro que isso afetará o desempenho. Com tabelas temporárias, você pode fazer isso apenas passando o nome da tabela temporáriaPara testar uma tabela temporária:
Para testar uma tabela variável:
outra coisa que experimentei é: se o seu esquema não tiver
GRANT
privilégio de criar tabelas, use tabelas variáveis.fonte
escrevendo dados em tabelas declaradas
declare @tb
e depois de me juntar a outras tabelas, percebi que o tempo de resposta comparado às tabelas temporáriastempdb .. # tb
é muito maior.Quando eu os uno ao @tb, o tempo é muito maior para retornar o resultado, ao contrário do #tm , o retorno é quase instantâneo.
Eu fiz testes com uma junção de 10.000 linhas e junção com 5 outras tabelas
fonte