No SQL Server 2005, podemos criar tabelas temporárias de duas maneiras:
declare @tmp table (Col1 int, Col2 int);
ou
create table #tmp (Col1 int, Col2 int);
Quais são as diferenças entre esses dois? Eu li opiniões conflitantes sobre se o @tmp ainda usa tempdb ou se tudo acontece na memória.
Em quais cenários um supera o outro?
sql-server
temp-tables
table-variable
Eric Z Beard
fonte
fonte
Respostas:
Existem algumas diferenças entre Tabelas Temporárias (#tmp) e Variáveis de Tabela (@tmp), embora o uso do tempdb não seja uma delas, conforme descrito no link do MSDN abaixo.
Como regra geral, para volumes pequenos e médios de dados e cenários de uso simples, você deve usar variáveis de tabela. (Esta é uma diretriz excessivamente ampla, com muitas exceções, é claro - veja abaixo e nos artigos a seguir.)
Alguns pontos a serem considerados ao escolher entre eles:
Tabelas temporárias são tabelas reais para que você possa fazer coisas como CREATE INDEXes, etc. Se você tiver grandes quantidades de dados para as quais o acesso por índice será mais rápido, as tabelas temporárias são uma boa opção.
As variáveis da tabela podem ter índices usando as restrições PRIMARY KEY ou UNIQUE. (Se você deseja um índice não exclusivo, inclua a coluna de chave primária como a última coluna na restrição exclusiva. Se você não tiver uma coluna exclusiva, poderá usar uma coluna de identidade.) O SQL 2014 também possui índices não exclusivos. .
Variáveis de tabela não participam de transações
SELECT
es estão implicitamente comNOLOCK
. O comportamento da transação pode ser muito útil, por exemplo, se você deseja ROLLBACK no meio de um procedimento, as variáveis de tabela preenchidas durante essa transação ainda serão preenchidas!As tabelas temporárias podem resultar na recompilação dos procedimentos armazenados, talvez com frequência. Variáveis de tabela não.
Você pode criar uma tabela temporária usando SELECT INTO, que pode ser mais rápido de escrever (bom para consultas ad-hoc) e pode permitir que você lide com a alteração dos tipos de dados ao longo do tempo, pois não é necessário definir a estrutura da tabela temporária antecipadamente.
Você pode passar variáveis de tabela de volta das funções, permitindo encapsular e reutilizar a lógica com muito mais facilidade (por exemplo, torne uma função dividir uma string em uma tabela de valores em algum delimitador arbitrário).
O uso de variáveis de tabela em funções definidas pelo usuário permite que essas funções sejam usadas mais amplamente (consulte a documentação de CREATE FUNCTION para obter detalhes). Se você estiver escrevendo uma função, use variáveis de tabela sobre tabelas temporárias, a menos que exista uma necessidade atraente.
As variáveis de tabela e as tabelas temporárias são armazenadas no tempdb. Porém, as variáveis de tabela (desde 2005) são padronizadas para o agrupamento do banco de dados atual versus as tabelas temporárias, que recebem o agrupamento padrão do tempdb ( ref ). Isso significa que você deve estar ciente dos problemas de agrupamento se o uso de tabelas temporárias e seu agrupamento de banco de dados for diferente do tempdb, causando problemas se você quiser comparar dados na tabela temporária com dados do banco de dados.
As tabelas temporárias globais (## tmp) são outro tipo de tabela temporária disponível para todas as sessões e usuários.
Algumas leituras adicionais:
A grande resposta de Martin Smith em dba.stackexchange.com
Perguntas freqüentes do MSDN sobre a diferença entre os dois: https://support.microsoft.com/en-gb/kb/305977
Artigo do blog MDSN: https://docs.microsoft.com/archive/blogs/sqlserverstorageengine/tempdb-table-variable-vs-local-temporary-table
Artigo: https://searchsqlserver.techtarget.com/tip/Temporary-tables-in-SQL-Server-vs-table-variables
Comportamentos inesperados e implicações de desempenho de tabelas temporárias e variáveis temporárias: Paul White no SQLblog.com
fonte
Basta olhar para a afirmação na resposta aceita que as variáveis da tabela não participam do log.
Parece geralmente falso que exista alguma diferença na quantidade de registro (pelo menos para
insert
/update
/delete
operações na tabela em si, embora eu tenha descoberto que há uma pequena diferença nesse aspecto para objetos temporários em cache nos procedimentos armazenados devido a tabela adicional do sistema atualizações).Analisei o comportamento do registro em relação a
@table_variable
e a#temp
tabela para as seguintes operações.Os registros do log de transações eram quase idênticos para todas as operações.
Na verdade, a versão da variável de tabela possui algumas entradas de log extras porque ela é adicionada (e removida posteriormente) à
sys.syssingleobjrefs
tabela base, mas no geral tinha poucos bytes registrados apenas como o nome interno das variáveis da tabela consome 236 bytes a menos do que nas#temp
tabelas (118nvarchar
caracteres a menos ).Script completo para reproduzir (melhor execução em uma instância iniciada no modo de usuário único e usando o
sqlcmd
modo)Resultados
fonte
INSERT ... SELECT
não eram minimamente registradas e você não podeSELECT INTO ...
uma variável de tabela.Para tabelas menores (menos de 1000 linhas), use uma variável temp, caso contrário, use uma tabela temp.
fonte
@wcm - na verdade, para escolher nit a variável de tabela não é apenas ram - ela pode ser parcialmente armazenada no disco.
Uma tabela temporária pode ter índices, enquanto uma variável da tabela pode ter apenas um índice primário. Se a velocidade é um problema As variáveis da tabela podem ser mais rápidas, mas obviamente se houver muitos registros ou a necessidade de pesquisar a tabela temporária de um índice em cluster, uma tabela temporária seria melhor.
Bom artigo de base
fonte
Tabela Temp: Uma tabela Temp é fácil de criar e fazer backup de dados.
Variável de tabela: Mas a variável de tabela envolve o esforço quando geralmente criamos as tabelas normais.
Tabela temporária: o resultado da tabela temporária pode ser usado por vários usuários.
Variável de tabela: Mas a variável de tabela pode ser usada apenas pelo usuário atual.
Tabela temporária: a tabela temporária será armazenada no tempdb. Isso criará tráfego de rede. Quando temos dados grandes na tabela temporária, ele precisa trabalhar no banco de dados. Existe um problema de desempenho.
Variável de tabela: mas uma variável de tabela será armazenada na memória física de alguns dados e, posteriormente, quando o tamanho aumentar, será movida para o tempdb.
Tabela Temp: a tabela Temp pode executar todas as operações DDL. Permite criar os índices, soltar, alterar, etc.,
Variável de tabela: enquanto a variável de tabela não permitirá realizar operações DDL. Mas a variável da tabela nos permite criar apenas o índice clusterizado.
Tabela temporária: a tabela temporária pode ser usada para a sessão atual ou global. Para que uma sessão com vários usuários possa utilizar os resultados na tabela.
Variável de tabela: Mas a variável de tabela pode ser usada até esse programa. (Procedimento armazenado)
Tabela Temp: a variável Temp não pode usar as transações. Quando fazemos as operações DML com a tabela temp, ela pode ser revertida ou confirmar as transações.
Variável de tabela: Mas não podemos fazer isso para a variável de tabela.
Tabela Temp: As funções não podem usar a variável temp. Mais ainda, não podemos executar a operação DML nas funções.
Variável de tabela: Mas a função nos permite usar a variável de tabela. Mas, usando a variável de tabela, podemos fazer isso.
Tabela Temp: O procedimento armazenado fará a recompilação (não é possível usar o mesmo plano de execução) quando usamos a variável temp para todas as chamadas subseqüentes.
Variável de tabela: Considerando que a variável de tabela não será assim.
fonte
Para todos vocês que acreditam no mito de que variáveis temporárias estão apenas na memória
Primeiro, a variável da tabela NÃO é necessariamente residente na memória. Sob pressão de memória, as páginas pertencentes a uma variável da tabela podem ser enviadas para tempdb.
Leia o artigo aqui: TempDB :: variável de tabela vs tabela temporária local
fonte
A outra principal diferença é que as variáveis de tabela não possuem estatísticas de coluna, como nas tabelas temporárias. Isso significa que o otimizador de consulta não sabe quantas linhas existem na variável da tabela (ele supõe 1), o que pode levar à geração de planos altamente não ideais se a variável da tabela realmente tiver um grande número de linhas.
fonte
rows
coluna insys.partitions
é mantida para as variáveis da tabela, para que ele realmente saiba quantas linhas existem na tabela. Isso pode ser visto usandoOPTION (RECOMPILE)
. Mas a falta de estatísticas da coluna significa que não é possível estimar predicados específicos da coluna.Citação retirada; Solução de problemas e internos profissionais do SQL Server 2012
VARIÁVEIS DE MESA NÃO SÃO CRIADAS NA MEMÓRIA
Existe um equívoco comum de que as variáveis de tabela são estruturas na memória e, como tal, terão desempenho mais rápido que as tabelas temporárias . Graças a um DMV chamado sys. dm _ db _ session _ space _ use, que mostra o uso do tempdb por sessão, você pode provar que não é esse o caso . Após reiniciar o SQL Server para limpar a DMV, execute o seguinte script para confirmar que o id da sua sessão retorna 0 para o usuário _ objetos _ alocar _ página _ contagem:
Agora você pode verificar quanto espaço uma tabela temporária usa executando o script a seguir para criar uma tabela temporária com uma coluna e preenchê-la com uma linha:
Os resultados no meu servidor indicam que a tabela foi alocada uma página no tempdb. Agora execute o mesmo script, mas use uma variável de tabela desta vez:
Qual usar?
fonte
Outra diferença:
Uma tabela var pode ser acessada apenas a partir de instruções no procedimento que a cria, e não de outros procedimentos chamados por esse procedimento ou SQL dinâmico aninhado (via exec ou sp_executesql).
O escopo de uma tabela temporária, por outro lado, inclui código nos procedimentos chamados e SQL dinâmico aninhado.
Se a tabela criada por seu procedimento precisar ser acessível a partir de outros procedimentos chamados ou SQL dinâmico, você deverá usar uma tabela temporária. Isso pode ser muito útil em situações complexas.
fonte
As diferenças entre
Temporary Tables (##temp/#temp)
eTable Variables (@table)
são as seguintes:Table variable (@table)
é criado nomemory
. Considerando que, aTemporary table (##temp/#temp)
é criado notempdb database
. No entanto, se houver uma pressão de memória, as páginas pertencentes a uma variável da tabela podem ser enviadas para tempdb.Table variables
não pode estar envolvidotransactions, logging or locking
. Isso faz@table faster then #temp
. Portanto, a variável de tabela é mais rápida que a tabela temporária.Temporary table
permite modificações de esquema diferentesTable variables
.Temporary tables
são visíveis na rotina criada e também nas rotinas filho. Considerando que, variáveis de tabela são visíveis apenas na rotina criada.Temporary tables
são permitidosCREATE INDEXes
enquanto,Table variables
não são permitidosCREATE INDEX
em vez disso, pode ter índice usandoPrimary Key or Unique Constraint
.fonte
Considere também que você pode frequentemente substituir as duas por tabelas derivadas, que também podem ser mais rápidas. Porém, como em todos os ajustes de desempenho, apenas testes reais em relação aos dados reais podem indicar a melhor abordagem para sua consulta específica.
fonte
Surpreende-me que ninguém tenha mencionado a principal diferença entre esses dois é que a tabela temporária suporta inserção paralela, enquanto a variável da tabela não. Você poderá ver a diferença no plano de execução. E aqui está o vídeo dos Workshops SQL no Canal 9 .
Isso também explica por que você deve usar uma variável temp para tabelas menores, caso contrário, use uma tabela temp, como SQLMenace respondeu anteriormente.
fonte