Qual é a diferença entre uma Expressão de tabela comum (CTE) e uma tabela temporária? E quando devo usar um sobre o outro?
CTE
WITH cte (Column1, Column2, Column3)
AS
(
SELECT Column1, Column2, Column3
FROM SomeTable
)
SELECT * FROM cte
Tabela Temp
SELECT Column1, Column2, Column3
INTO #tmpTable
FROM SomeTable
SELECT * FROM #tmpTable
sql-server
cte
Rachel
fonte
fonte
Respostas:
Isso é bem amplo, mas eu darei uma resposta o mais geral possível.
CTEs ...
VIEW
s#Temp Tables ...
Quanto a quando usar cada um, eles têm casos de uso muito diferentes. Se você tiver um conjunto de resultados muito grande ou precisar consultá-lo mais de uma vez, coloque-o em uma
#temp
tabela. Se ele precisa ser recursivo, é descartável ou é apenas para simplificar algo logicamente, aCTE
é o preferido.Além disso, um nunca
CTE
deve ser usado para desempenho . Você quase nunca acelera as coisas usando um CTE, porque, novamente, é apenas uma visão descartável. Você pode fazer algumas coisas legais com eles, mas acelerar uma consulta não é realmente uma delas.fonte
EDITAR:
Por favor, veja os comentários de Martin abaixo:
Resposta original
CTE
Leia mais no MSDN
Um CTE cria a tabela que está sendo usada na memória, mas é válida apenas para a consulta específica a seguir. Ao usar a recursão, isso pode ser uma estrutura eficaz.
Você também pode considerar o uso de uma variável de tabela. Isso é usado quando uma tabela temporária é usada e pode ser usada várias vezes sem precisar ser materializado novamente para cada junção. Além disso, se você precisar persistir alguns registros agora, adicione mais alguns registros após a próxima seleção, adicione mais alguns registros após outra operação e, em seguida, retorne apenas alguns poucos registros, pois isso pode ser uma estrutura útil, pois não precisa ser descartado após a execução. Principalmente apenas açúcar sintático. No entanto, se você mantiver a contagem de linhas baixa, ela nunca se materializa em disco. Consulte Qual é a diferença entre uma tabela temporária e uma variável de tabela no SQL Server? para mais detalhes.
Tabela Temp
Leia mais no MSDN - role para baixo cerca de 40% do caminho
Uma tabela temporária é literalmente uma tabela criada em disco, apenas em um banco de dados específico que todos sabem que pode ser excluído. É de responsabilidade de um bom desenvolvedor destruir essas tabelas quando elas não são mais necessárias, mas um DBA também pode limpá-las.
As tabelas temporárias são fornecidas em duas variedades: local e global. Em termos de MS Sql Server, você usa uma
#tableName
designação para local e##tableName
designação para global (observe o uso de um único ou duplo # como a característica de identificação).Observe que, com tabelas temporárias, ao contrário de variáveis de tabela ou CTE, é possível aplicar índices e similares, pois são legitimamente tabelas no sentido normal da palavra.
Geralmente eu usaria tabelas temporárias para consultas maiores ou maiores, e CTEs ou variáveis de tabela se já tivesse um pequeno conjunto de dados e quisesse rapidamente criar um pouco de código para algo pequeno. A experiência e os conselhos de outras pessoas indicam que você deve usar CTEs nas quais um pequeno número de linhas é retornado. Se você tiver um número grande, provavelmente se beneficiaria da capacidade de indexar na tabela temporária.
fonte
SELECT Column1, Column2, Column3 FROM SomeTable
WITH T(X) AS (SELECT NEWID())SELECT * FROM T T1 JOIN T T2 ON T1.X=T2.X
, verifique também os planos de execução. Embora às vezes seja possível hackear o plano para obter um carretel. Há um item de conexão solicitando uma dica para isso.A resposta aceita aqui diz que "uma CTE nunca deve ser usada para desempenho" - mas isso pode enganar. No contexto de CTEs versus tabelas temporárias, acabei de remover uma faixa de lixo de um conjunto de procs armazenados, porque alguns idiotas devem ter pensado que havia pouca ou nenhuma sobrecarga no uso de tabelas temporárias. Enfiei o lote nas CTEs, exceto aquelas que seriam legitimamente reutilizadas durante todo o processo. Ganhei cerca de 20% de desempenho em todas as métricas. Comecei a remover todos os cursores que estavam tentando implementar o processamento recursivo. Foi aqui que vi o maior ganho. Acabei reduzindo o tempo de resposta por um fator de dez.
CTEs e tabelas temporárias têm casos de uso muito diferentes. Eu só quero enfatizar que, embora não seja uma panacéia, a compreensão e o uso correto de CTEs podem levar a algumas melhorias realmente estelares na qualidade / manutenção e velocidade do código. Desde que eu os identifiquei, vejo tabelas temporárias e cursores como os grandes males do processamento SQL. Eu posso me dar bem com variáveis de tabela e CTEs para quase tudo agora. Meu código é mais limpo e rápido.
fonte
Um CTE pode ser chamado repetidamente em uma consulta e é avaliado toda vez que é referenciado - esse processo pode ser recursivo. Se for apenas referido uma vez, ele se comportará como uma subconsulta, embora os CTEs possam ser parametrizados.
Uma tabela temporária é mantida fisicamente e pode ser indexada. Na prática, o otimizador de consulta também pode persistir nos resultados intermediários de junção ou subconsulta nos bastidores, como em operações de spool, portanto, não é estritamente verdade que os resultados dos CTEs nunca sejam persistidos no disco.
As variáveis de tabela IIRC (por outro lado) são sempre estruturas na memória.
fonte
A tabela Temp é um objeto real no tempdb, mas cte é apenas um tipo de invólucro em torno de consultas complexas para simplificar a sintaxe da recursão da organização em uma única etapa.
fonte
O principal motivo para usar CTEs é acessar as Funções da Janela, como
row_number()
várias outras.Isso significa que você pode fazer coisas como obter a primeira ou a última linha por grupo MUITO MUITO rápido e eficiente - com mais eficiência do que outros meios na maioria dos casos práticos .
Você pode executar uma consulta semelhante à anterior usando uma subconsulta correlacionada ou usando uma subconsulta, mas o CTE será mais rápido em quase todos os cenários.
Além disso, os CTEs podem realmente ajudar a simplificar seu código. Isso pode levar a ganhos de desempenho, porque você entende mais a consulta e pode introduzir mais lógica de negócios para ajudar o otimizador a ser mais seletivo.
Além disso, os CTEs podem melhorar o desempenho se você entender sua lógica de negócios e souber quais partes da consulta devem ser executadas primeiro - normalmente, coloque primeiro as consultas mais seletivas que levam a conjuntos de resultados que podem usar um índice na próxima associação e adicionar a
option(force order)
consulta dicaPor fim, os CTEs não usam o tempdb por padrão, então você reduz a contenção nesse gargalo através do uso deles.
Tabelas temporárias devem ser usadas se você precisar consultar os dados várias vezes ou, alternativamente, se você medir suas consultas e descobrir isso inserindo em uma tabela temporária e adicionando um índice para melhorar seu desempenho.
fonte
Parece haver um pouco de negatividade aqui em relação às CTEs.
Meu entendimento de um CTE é que é basicamente um tipo de visão ad-hoc. O SQL é uma linguagem declarativa e uma baseada em conjunto. Os CTEs são uma ótima maneira de declarar um conjunto! Não ser capaz de indexar uma CTE é realmente uma coisa boa, porque você não precisa! É realmente um tipo de açúcar sintático para facilitar a leitura / gravação da consulta. Qualquer otimizador decente elaborará o melhor plano de acesso usando índices nas tabelas subjacentes. Isso significa que você pode efetivamente acelerar sua consulta CTE seguindo os conselhos do índice nas tabelas subjacentes.
Além disso, apenas porque você definiu um conjunto como um CTE, isso não significa que todas as linhas no conjunto devem ser processadas. Dependendo da consulta, o otimizador pode processar linhas "apenas o suficiente" para satisfazer a consulta. Talvez você só precise dos 20 primeiros para sua tela. Se você construiu uma tabela temporária, realmente precisa ler / gravar todas essas linhas!
Com base nisso, eu diria que os CTEs são um ótimo recurso do SQL e podem ser usados em qualquer lugar que facilite a leitura da consulta. Eu pensaria apenas em uma tabela temporária para um processo em lote que realmente precisaria processar todos os registros. Mesmo assim, o afaik não é realmente recomendado, porque em uma tabela temporária é muito mais difícil para o banco de dados ajudá-lo com o cache e os índices. Talvez seja melhor ter uma tabela permanente com um campo PK exclusivo para sua transação.
Eu tenho que admitir que minha experiência é principalmente com o DB2, então estou assumindo que o CTE funcione de maneira semelhante nos dois produtos. Ficarei feliz em corrigi-lo se os CTEs forem de alguma forma inferiores no SQL Server. ;)
fonte