Quand sp_executesql actualise-t-il le plan de requête?

13

Vous devrez pardonner ma naïveté car je ne suis pas un administrateur de base de données, mais je crois comprendre qu'au fil du temps, les statistiques d'une modification de la base de données et une procédure stockée doivent être recompilées pour maintenir le plan de requête à jour avec les dernières statistiques.

En supposant que j'ai une procédure stockée dans ma base de données qui est recompilée avec les dernières statistiques à un intervalle régulier, quelles sont les implications de l'incrustation de la procédure stockée dans le code et de l'encapsuler dans une sp_executesqlinstruction? Est-ce que je perds l'actualisation du plan de requête qui se produisait dans le cadre de la recompilation de la procédure?

S'il y a autre chose (autre que des autorisations) que je dois considérer avant de faire ce changement, j'apprécierais vos idées.

J'ai lu ceci sur MSDN:

La capacité de l'optimiseur de requêtes SQL Server à faire correspondre la nouvelle chaîne Transact-SQL avec un plan d'exécution existant est entravée par les valeurs de paramètre en constante évolution dans le texte de la chaîne, en particulier dans les instructions Transact-SQL complexes.

Donc, en supposant que la procédure stockée que j'essaie de connecter et de boucler sp_executesqlcontient effectivement certains paramètres, cela signifie-t-il que bien que mon plan d'exécution soit mis en cache, je rend plus difficile pour SQL Server de le trouver et de le réutiliser?

james lewis
la source

Réponses:

7

La ligne de MSDN parle d'utiliser EXEC(), comme ceci:

SET @sql = 'SELECT foo FROM dbo.bar WHERE x = ''' + @x + ''';';
EXEC(@sql);

Dans mes tests, les versions modernes de SQL Server sont toujours en mesure de réutiliser un plan comme celui-ci, mais il peut y avoir d'autres variables (telles que la version, ou par exemple si vous ajoutez des WHEREclauses conditionnelles basées sur la présence de certains paramètres - auquel cas cela générera un plan différent).

Si vous utilisez, sp_executesqlles valeurs des paramètres peuvent toujours provoquer des problèmes de reniflage de paramètres (comme avec le SQL normal), mais cela n'a rien à voir avec la possibilité que SQL Server puisse réutiliser le plan. Ce plan sera utilisé maintes et maintes fois, comme si vous ne l'aviez pas utilisé sp_executesqldu tout, à moins que les variables qui entraîneraient une requête directe soient recompilées, auquel cas celle-ci sera également recompilée (essentiellement, SQL Server ne stocker quoi que ce soit avec le plan qui dit "cela a été exécuté à partir de sp_executesql, mais celui-ci ne l'était pas):

SET @sql = N'SELECT foo FROM dbo.bar WHERE x = @x;';
EXEC sp_executesql @sql, N'@x VARCHAR(32)', @x;

En prime, cela a une protection intégrée contre le SQL dynamique et vous évite d'avoir à vous soucier de doubler les guillemets simples en raison des délimiteurs de chaînes. J'ai blogué à ce sujet ici .

Si vous rencontrez des problèmes avec le plan de réutilisation et / ou renifler paramètre, certaines choses que vous devriez regarder dans sont OPTION (RECOMPILE), OPTIMIZE FOR, optimize for ad hoc workloadset simple/forced parameterization. J'ai répondu à quelques questions similaires en réponse à une récente webdiffusion ici, cela peut valoir le coup d'œil:

http://sqlperformance.com/performance-palooza

L'essentiel est: n'ayez pas peur de l'utiliser sp_executesql, mais n'utilisez-le que lorsque vous en avez besoin, et ne dépensez de l'énergie que pour une optimisation excessive lorsque vous avez un problème de performance réel. L'exemple ci-dessus est terrible car il n'y a aucune raison d'utiliser du SQL dynamique ici - j'ai écrit cette réponse en supposant que vous avez un cas d'utilisation légitime.

Aaron Bertrand
la source
2

Les requêtes qui sont exécutées via sp_executesql suivent les mêmes règles de plans d'exécution que les requêtes normales qui ne sont pas exécutées via sp_executesql. Si le texte de la requête change, un nouveau plan est créé. Si le texte ne change pas à cause de l'utilisateur des paramètres, le plan est réutilisé. Lorsque les statistiques sont mises à jour, les plans expirent et de nouveaux plans sont générés lors de la prochaine exécution de la requête.

mrdenny
la source
Merci pour votre réponse, j'ai fait une modification concernant les paramètres car j'ai maintenant réalisé que chaque fois que j'appelle sp_ExecuteSql, j'utiliserai une chaîne différente comme requête, car du point de vue de Sql Server, j'ai remplacé les paramètres avec des valeurs codées en dur (ils seront entrés dans le code avant d'envoyer ma requête à Sql Server). Connaissez-vous un moyen de contourner cela? La déclaration de variables dans mon instruction SQL en ligne aiderait-il l'optimiseur de requêtes à trouver mon plan de requête mis en cache?
james lewis