12

J'ai une requête complexe que je dois utiliser dans une requête ultérieure (en fait une instruction de mise à jour). J'ai essayé les deux en utilisant un CTE et une table temporaire. La performance en utilisant le CTE est horrible par rapport à l'approche de la table temporaire. C'est quelque chose comme 15 secondes vs millisecondes. Pour simplifier le test au lieu de rejoindre la table CTE/Temp dans la requête suivante, je l'ai simplement sélectionné *. Dans ce cas, ils effectuent la même chose. J'ai regardé le plan d'exécution pour les deux approches à la fois avec les jointures dans la requête suivante, puis sélectionnez simplement *. Avec la sélection simple, les plans de requête sont à peu près les mêmes, mais avec les jointures dans la sélection suivante, les plans de requête ne le sont pas. Plus précisément, la partie du plan de requête pour créer et remplir la table temporaire reste la même, tandis que la partie du plan de requête pour créer et remplir le CTE change radicalement lorsqu'elle est ensuite utilisée dans une requête avec une jointure.SQL 2005 CTE par rapport à la table TEMP Performances lors de l'utilisation dans les jointures d'autres tables

Ma question est pourquoi le plan de requête pour la création et la population du CTE change par la façon dont il est ensuite utilisé alors que la table temporaire ne l'est pas. Aussi dans quels scénarios alors un CTE donnerait de meilleures performances qu'une table temporaire?

* Remarque J'ai également utilisé une variable de table et elle est comparable à l'approche de la table temporaire.

Merci

Répondre

9

Vous posez une question compliquée, vous obtenez donc une réponse compliquée: cela dépend. (Je déteste cette réponse).

Sérieusement, cependant, cela a à voir avec la façon dont l'optimiseur choisit un plan de données (que vous connaissiez déjà); une table temporaire ou variable est comme une structure permanente en ce qu'un plan d'exécution effectuera l'opération associée au remplissage de cette structure en premier, puis utilisera cette structure dans les opérations suivantes. Un CTE n'est PAS une table temporaire; l'utilisation de l'ECU n'est pas calculée tant qu'elle n'est pas utilisée par les opérations subséquentes et que l'utilisation influe sur l'optimisation du plan.

Les CTE ont été mis en œuvre pour des problèmes de réutilisation et de maintenance, pas nécessairement des performances; Cependant, dans de nombreux cas (comme la récursivité), ils fonctionneront mieux que les méthodes de codage traditionnelles.

13

CTE est juste un alias pour la requête.

Il peut (ou ne peut pas) être réexécuté chaque fois qu'il est utilisé.

Il n'y a aucun moyen propre à la force CTE matérialisation dans SQL Server (comme Oracle de /*+ MATERIALIZE */), et vous devez faire des tours sales comme ceci:

CTE peut améliorer les performances en cas d'utilisation dans les plans ne nécessitant qu'une seule évaluation (par exemple HASH JOIN, MERGE JOIN etc.).

Dans ces scénarios, la table de hachage sera construite directement à partir du CTE, tandis que l'utilisation de la table temporaire nécessitera l'évaluation du CTE, l'extraction des résultats dans la table temporaire et la lecture de la table temporaire à nouveau.

+1

Oui pour matérialiser! Un PK/IX dans la définition pourrait être gentil. – crokusek

2

Je trouve que typiquement un CTE répété n'obtient aucune amélioration des performances.Ainsi, par exemple, si vous utilisez un CTE pour remplir une table et ensuite le même CTE à joindre dans une requête ultérieure, aucun avantage. Malheureusement, les CTE ne sont pas des instantanés et ils doivent littéralement être répétés pour être utilisés dans deux déclarations distinctes, ils ont donc tendance à être évalués deux fois. À la place des CTE, j'utilise souvent des TVF en ligne (qui peuvent contenir des CTE), ce qui permet une réutilisation correcte, et n'est pas meilleur ou pire que les CTE dans mes SP. En outre, je trouve également que le plan d'exécution peut être mauvais si la première étape modifie les statistiques de telle sorte que le plan d'exécution de la deuxième étape est toujours inexact car il est évalué avant l'exécution de toutes les étapes. Dans ce cas, je cherche à stocker manuellement les résultats intermédiaires, à m'assurer qu'ils sont correctement indexés et à diviser le processus en plusieurs SP et à ajouter WITH RECOMPILE pour que les futurs SP aient des plans qui soient bons pour les données qu'ils sont. va effectivement opérer.

0

J'ai essayé de créer CTE avec simple sélectionné avec le filtre de la grande table Puis 3 fois sous-perçu il. Ensuite, faites de même avec les tables temporaires.

Le résultat était 70% de temps pour CTE -30% de temps pour la table temporaire. Donc la table temporaire est meilleure pour ces solutions.

Je ne pense pas que CTE fasse une table temporaire seulement avec la requête sélectionnée, mais 3 fois rends la sélection à une grande table.

Questions connexes