Il m'a été suggéré que l'utilisation d'instructions IF dans des lots t-SQL nuisait aux performances. J'essaie de trouver une confirmation ou de valider cette affirmation. J'utilise SQL Server 2005 et 2008.
L'affirmation est qu'avec le lot suivant: -
IF @parameter = 0
BEGIN
SELECT ... something
END
ELSE
BEGIN
SELECT ... something else
END
SQL Server ne peut pas réutiliser le plan d'exécution généré car la prochaine exécution peut nécessiter une branche différente. Cela implique que SQL Server éliminera entièrement une branche du plan d'exécution sur la base du fait que pour l'exécution en cours, il peut déjà déterminer quelle branche est nécessaire. Est-ce vraiment vrai?
De plus ce qui se passe dans ce cas: -
IF EXISTS (SELECT ....)
BEGIN
SELECT ... something
END
ELSE
BEGIN
SELECT ... something else
END
où il n'est pas possible de déterminer à l'avance quelle branche sera exécutée?
sql-server
sql-server-2008
sql-server-2005
query-performance
AnthonyWJones
la source
la source
Réponses:
SQL Server optimise le processus de compilation du plan de requête pour la procédure stockée en ignorant les branches conditionnelles à l'intérieur de la procédure stockée. Le plan sera généré en fonction des paramètres utilisés pour la première exécution, cela posera des problèmes si les paramètres sont différents pour les branches.
Je placerais le SQL de chacune des branches dans leur propre procédure stockée, de sorte que le plan généré soit basé sur l'utilisation réelle des paramètres de cette branche.
la source
Le seul raccourci sera
IF 1 = 1
@Parameter et EXISTS nécessitent toujours un traitement pour le "cas général" (par
@parameter = 42
exemple)En disant que ... que dit le plan d'exécution réel ainsi que le profileur capturant les événements de recomplition? (Je n'aime pas les plans estimés selon la réponse de Jao)
la source
Essayez d'afficher le plan d'exécution estimé, pas le réel. Vous verrez que le premier contient l'
COND
opérateur.Cet opérateur a également été inclus dans le plan d'exécution mis en cache. Dans votre exemple, le plan d'excution estimé contiendra un opérateur COND et 2 branches SELECT et sera donc entièrement réutilisable. Parce que lors de l'exécution d'un lot, SQL Server évalue non seulement les instructions DML mais aussi toutes les autres, en les obtenant du plan.
Le plan d'exécution interne est une structure similaire à l'arborescence des expressions.
la source
Les plans seront créés en fonction des paramètres transmis, donc en réalité, je dirais que non - une logique conditionnelle qui est normalement basée sur des paramètres ne nuit pas aux performances.
Vous obtiendrez plusieurs plans produits, en supposant que les paramètres provoquent suffisamment de variance pour que l'optimiseur de requête le remarque.
Vous pouvez voir lequel en activant le plan Show Execution, en exécutant les scripts - notez les différences dans le plan. Lorsque vous exécutez les procédures (je suppose que les procédures stockées ici), vous remarquerez que la première fois est généralement plus rapide, le deuxième hit utilise le plan stocké. Modifiez les paramètres et répétez puis exécutez les paramètres d'origine - en théorie, le plan sera toujours dans le cache, mais cela dépend de l'utilisation du serveur (ticks de cache - ils ne restent pas éternellement ..) etc.
la source
Peut-être que cela a été amélioré en 2005 et 2008, mais l'utilisation de conditions en 2000 serait probablement pire que ce que vous décrivez, il compilerait un plan pour gérer au mieux la première exécution de la procédure, puis utiliserait ce plan pour exécuter la procédure même lorsque les conditions modifié. D'après mon expérience, cela a provoqué des requêtes qui s'exécutaient en quelques minutes pour s'exécuter en quelques heures. Bien que j'utilise 2008 maintenant et que j'utilise 2005, je ne peux pas commenter le fonctionnement des coditions là-bas puisque je ne les utilise plus.
la source