Nesta excelente questão SO , as diferenças entre CTE
esub-queries
foram discutidas.
Gostaria de perguntar especificamente:
Em que circunstância cada um dos seguintes itens é mais eficiente / mais rápido?
- CTE
- Subconsulta
- Tabela Temporária
- Variável de tabela
Tradicionalmente, eu usei muito temp tables
no desenvolvimento stored procedures
- pois eles parecem mais legíveis do que muitas subconsultas entrelaçadas.
Non-recursive CTE
s encapsulam conjuntos de dados muito bem e são muito legíveis, mas existem circunstâncias específicas em que se pode dizer que sempre terão um desempenho melhor? ou é um caso de ter que sempre mexer nas diferentes opções para encontrar a solução mais eficiente?
EDITAR
Recentemente me disseram que, em termos de eficiência, as tabelas temporárias são uma boa primeira opção, pois possuem um histograma associado, ou seja, estatísticas.
Respostas:
SQL é uma linguagem declarativa, não uma linguagem processual. Ou seja, você constrói uma instrução SQL para descrever os resultados que deseja. Você não está dizendo ao mecanismo SQL como fazer o trabalho.
Como regra geral, é uma boa ideia deixar o mecanismo e o otimizador de SQL encontrar o melhor plano de consulta. Há muitos anos-pessoa dedicados ao desenvolvimento de um mecanismo SQL, portanto, deixe os engenheiros fazerem o que sabem fazer.
Obviamente, há situações em que o plano de consulta não é ideal. Então você deseja usar dicas de consulta, reestruturar a consulta, atualizar estatísticas, usar tabelas temporárias, adicionar índices e assim por diante para obter melhor desempenho.
Quanto à sua pergunta. O desempenho de CTEs e subconsultas deve, em teoria, ser o mesmo, pois ambos fornecem as mesmas informações para o otimizador de consultas. Uma diferença é que uma CTE usada mais de uma vez pode ser facilmente identificada e calculada uma vez. Os resultados podem ser armazenados e lidos várias vezes. Infelizmente, o SQL Server não parece tirar proveito desse método básico de otimização (você pode chamar essa eliminação de subconsulta comum).
As tabelas temporárias são uma questão diferente, porque você fornece mais orientações sobre como a consulta deve ser executada. Uma grande diferença é que o otimizador pode usar estatísticas da tabela temporária para estabelecer seu plano de consulta. Isso pode resultar em ganhos de desempenho. Além disso, se você tiver uma CTE (subconsulta) complicada usada mais de uma vez, armazená-la em uma tabela temporária geralmente oferecerá um aumento no desempenho. A consulta é executada apenas uma vez.
A resposta para sua pergunta é que você precisa brincar para obter o desempenho esperado, principalmente para consultas complexas que são executadas regularmente. Em um mundo ideal, o otimizador de consultas encontraria o caminho de execução perfeito. Embora isso aconteça com frequência, você poderá encontrar uma maneira de obter melhor desempenho.
fonte
Não existe regra. Acho as CTEs mais legíveis e as uso a menos que que apresentem algum problema de desempenho. Nesse caso, investigo o problema real em vez de supor que o CTE é o problema e tento reescrevê-lo usando uma abordagem diferente. Geralmente, há mais do que a maneira que escolhi declarar declaradamente minhas intenções com a consulta.
Certamente, há casos em que você pode desvendar CTEs ou remover subconsultas e substituí-las por uma tabela #temp e reduzir a duração. Isso pode ser devido a várias coisas, como estatísticas obsoletas, incapacidade de obter estatísticas precisas (por exemplo, ingressar em uma função com valor de tabela), paralelismo ou até incapacidade de gerar um plano ideal devido à complexidade da consulta ( nesse caso, quebrá-lo pode dar ao otimizador uma chance de lutar). Mas também existem casos em que a E / S envolvida na criação de uma tabela #temp pode superar os outros aspectos de desempenho que podem tornar um plano específico moldar usando um CTE menos atraente.
Honestamente, existem muitas variáveis para fornecer uma resposta "correta" à sua pergunta. Não há uma maneira previsível de saber quando uma consulta pode se inclinar a favor de uma abordagem ou de outra - apenas saiba que, em teoria, a mesma semântica para uma CTE ou uma única subconsulta deve executar exatamente a mesma. Acho que sua pergunta seria mais valiosa se você apresentar alguns casos em que isso não é verdade - pode ser que você tenha descoberto uma limitação no otimizador (ou uma conhecida) ou pode ser que suas consultas não sejam semanticamente equivalentes ou aquele contém um elemento que impede a otimização.
Por isso, sugiro que você escreva a consulta da maneira que lhe parecer mais natural e só se desvie quando descobrir um problema real de desempenho que o otimizador está tendo. Pessoalmente, eu os classifico como CTE e, em seguida, subconsulta, com a #temp table sendo o último recurso.
fonte
link / edit / close / flag
- se houver votos para encerrá-la, você veráclose (n)
onden
representa o número de usuários que votaram para encerrá-la. Se você clicar no link, verá os motivos pelos quais esses usuários selecionaram.#temp é materializado e o CTE não.
CTE é apenas sintaxe, portanto, em teoria, é apenas uma subconsulta. É executado. #temp é materializado. Portanto, um CTE caro em uma junção executada muitas vezes pode ser melhor em uma #temp. Por outro lado, se é uma avaliação fácil que não é executada, mas algumas vezes não vale a sobrecarga de #temp.
Existem algumas pessoas no SO que não gostam de variáveis de tabela, mas eu gosto delas porque elas são materializadas e mais rápidas de criar do que #temp. Há momentos em que o otimizador de consulta se sai melhor com uma #temp em comparação com uma variável de tabela.
A capacidade de criar uma PK em uma variável #temp ou table fornece ao otimizador de consulta mais informações que uma CTE (como você não pode declarar uma PK em uma CTE).
fonte
Apenas duas coisas que eu acho que tornam SEMPRE preferível usar uma # Temp Table em vez de uma CTE são:
Você não pode colocar uma chave primária em um CTE, para que os dados acessados pelo CTE tenham que percorrer cada um dos índices nas tabelas do CTE, em vez de acessar o PK ou Index na tabela temporária.
Como você não pode adicionar restrições, índices e chaves primárias a um CTE, eles são mais propensos a erros de entrada e erros.
-Onedaywhen ontem
Aqui está um exemplo em que restrições de #table podem impedir dados incorretos, o que não é o caso nos CTEs.
fonte
ALWAYS
é um pouco longe demais, mas obrigado pela resposta. Em termos de legibilidade, o uso de CTEs pode ser uma coisa boa.CHECK
restrição referente a várias linhas / tabelas é não permitido). Você pode postar um exemplo em que um CTE exibe um erro que a tabela temporária equivalente não possui?