J'ai une instruction de suppression qui utilise un mauvais plan lorsqu'elle est exécutée dans une procédure stockée, mais choisit un bien meilleur plan lorsqu'elle est exécutée ad hoc.
J'ai reconstruit tous les index des tables utilisées par la requête et supprimé tous les caches. L'optimiseur choisit toujours le mauvais plan pour la procédure stockée.
Je voudrais savoir pourquoi l'optimiseur utilise un plan d'exécution différent pour la procédure stockée par rapport au SQL ad hoc.
MISE À JOUR: Je suppose que ce doit être les paramètres après tout - quand j'ai exécuté le code ad-hoc avec la variable codée en dur, je peux obtenir le "mauvais" plan avec la bonne valeur (c'est une date, des valeurs qui ont un an semblent générer le "bon" plan). Maintenant, essayons de forcer le "bon" plan sur le proc en utilisant un indice de requête.
SOLUTION: J'ai fini par obtenir le plan que je voulais en utilisant le conseil OPTIMISER POUR INCONNU.
la source
WHERE
clause?Réponses:
Les suspects habituels:
Point 1: l'optimiseur peut choisir le meilleur plan pour les constantes.
Changer les constantes = changer le plan. Un plénum paramétré est réutilisable
Le point 2 introduira des conversions implicites en raison de la priorité du type de données,
par exemple la colonne varchar par rapport au paramètre nvarchar
Point 3: utiliser le masquage des paramètres ou OPTIMISER POUR INCONNU
Modifier: Pour tester: exécuter le proc stocké, exécuter sp_updatestats, réexécuter. Cela invalidera les plans mis en cache, ce qui est mieux que de vider le cache du plan
Edit: après le commentaire de jcolebrand
Vous pouvez désactiver le reniflement de plusieurs manières. Les 3 principaux sont
Masquage des paramètres:
Le masquage et l'indice OPTIMIZE ont le même effet (peut-être pour des raisons différentes). Autrement dit, l'optimiseur doit utiliser des statistiques et la distribution des données ( Remarque: toujours en cours de test par Mark Storey-Smith )
évaluer les paramètres sur leurs propres mérites ?, plutôt que ce qu'ils étaient lors du dernier appel. L'optimiseur peut recompiler ou non. SQL Server 2005 a ajouté une recompilation au niveau des instructions afin qu'il y ait moins d'impactMaintenant, pourquoi un plan avec des paramètres "reniflés" est "collant" par rapport aux paramètres masqués / "inconnus", je ne suis pas sûr.
J'ai utilisé le masquage des paramètres depuis SQL Server 2000 pour tout sauf le code le plus simple. J'ai remarqué que cela pouvait se produire avec un code plus complexe. Et à mon ancien travail, j'ai quelques rapports procs que je pouvais changer les valeurs par défaut des paramètres du plan. Je pense que l'approche "culte du fret" était plus facile qu'un appel de support.
Edit 2, 12 oct 2011, après quelques discussions
Le masquage des paramètres et OPTIMISER POUR INCONNU ont le même effet pour autant que je sache.
L'astuce est plus propre que le masquage mais a été ajoutée avec SQL Server 2008.
Le reniflage des paramètres se produit au moment de la compilation.
WITH RECOMPILE génère un nouveau plan à chaque exécution. Cela signifie qu'un mauvais choix de valeurs par défaut influencera le plan. Lors de mon dernier travail, j'ai pu le démontrer facilement avec du code de rapport: la modification des valeurs par défaut des paramètres a modifié le plan indépendamment des paramètres fournis.
Cet article MS Connect est intéressant: utilisation d'index sous-optimale dans la procédure stockée (mentionnée dans l'une des réponses SO ci-dessous)
Problèmes en suspens
Le reniflement s'applique-t-il toujours à WITH RECOMPILE? Autrement dit, si l'optimiseur sait rejeter le plan, vise-t-il à le réutiliser?
Pourquoi les plans reniflés sont-ils "collants"?
Liens depuis SO:
https://stackoverflow.com/q/272726/27535
Remus Rusanu (équipe MS SQL) et moi avons eu un bunfight ici sur SO
la source
OPTION (RECOMPILE)
ou l'ensemble du processusWITH RECOMPILE
pour forcer SQL Server à ignorer les plans existants.OPTIMIZE
parce que Microsoft est une entreprise américaine. :)N'oubliez pas que les paramètres ANSI que vous avez configurés pour le plan de connexion jouent un rôle dans la sélection du plan d'exécution. Lorsque l'application appelle la procédure stockée, elle a probablement des paramètres ANSI différents de votre connexion SSMS.
la source