web-dev-qa-db-fra.com

Les procédures stockées SQL Server fonctionnent très lentement après un certain temps

Nous avons une application ASP.NET avec une page de rapport qui exécute plusieurs procédures stockées. Nous avons un problème avec un système de production dans lequel le rapport s'exécute si lentement que cela puisse sortir lorsque l'utilisateur sélectionne une plage de date plus longue.

Lorsque le ralentissement survient, nous sommes en mesure de restaurer la fonctionnalité en exécutant EXEC sp_recompile 'CrucialTable' Sur une table touchée par toutes les procédures stockées, puis exécutez immédiatement le rapport pour une plage de date longue. Cela fixe le problème pendant un moment, mais il rampe lentement.

Mon hypothèse était un mauvais plan d'exécution alors j'ai ajouté WITH RECOMPILE Aux procédures stockées, mais malheureusement, cela n'a pas résolu le problème.

Nous utilisons SQL Azure si cela fait toute différence.

MISE À JOUR

J'ai découvert quelques SP qui manquaient toujours les options de recompilisation afin que cela ait été ajouté et que nous avons maintenant un nouveau problème. Les rapports de longue date de la longue date fonctionnent bien (moins de 4 secondes qui conviennent parfaitement à la quantité de crunching qui se déroule), mais curieusement maintenant, les rapports de courte gamme fonctionnent horriblement. Par exemple, un rapport qui couvre 2 ans de transactions de 2 ans environ 3,5 secondes, mais 2 semaines prend 20 secondes!

Mise à jour 2

J'ai réussi à reproduire le problème sur une machine DEV et jetez un coup d'œil au plan d'exécution. J'ai essayé un radeau d'options combinaisons comme OPTION(RECOMPILE) et OPTIMIZE mais comme il s'avère que la requête elle-même fonctionne assez vite.

Le problème est que

La requête a dû attendre XX secondes pour Mistmentgrant pendant l'exécution

xX variait de 20 à 90 secondes en fonction de la course.

Cela m'a frappé comme un mais inhabituel car il n'y avait pas d'autres requêtes qui courent à l'époque et que la machine DEV a beaucoup de bélier. Le plan d'exécution a également suggéré un index manquant pour que je vais essayer d'ajouter cela et de voir si cela aide.

Mise à jour

J'ai expérimenté un certain nombre d'options de recompilation/optimisation, mais la solution me échappe toujours.

Fondamentalement, les procédures stockées ont tous des options de recompilation sur eux maintenant, et tout ce qui fonctionne, tout fonctionne bien, même avec de grandes données (les requêtes prennent moins d'une seconde). Mon problème initial de Mishgrant s'est arrêté, ce qui, à mon avis, était juste parce que lors de l'heure de la machine, il y avait beaucoup d'applications ouvertes et était un peu basse sur la RAM gratuite.

En production, nous avons maintenant tous les SP avec les mêmes options de recompilation, mais malheureusement, les requêtes de courte gamme continuent d'être incroyablement lentes. J'ai exécuté les mêmes SPS à l'aide de SSMS vers la DB de production (avec ArithaBort défini sur OFF pour simuler une connexion similaire) et elles fonctionnent pratiquement instantanément indépendamment de la portée longue ou courte.

Lors de l'exécution du rapport de plage de courte portée de l'application en production, une entrée dans la table sys.dm_exec_query_memory_grants Pendant environ 12 secondes. Le rapport complet prend ensuite encore plus de 14 secondes à remplir après que cette entrée a disparu.

3
BenC3

Ce que vous décrivez des sons comme le paramètre me renifler. Le paramètre reniflant se produit car SQL Server met en cache le plan d'exécution de la procédure si le plan ne se trouve pas dans le cache. Les exécutions ultérieures utiliseront cette version du plan. Dans la plupart des cas, c'est souhaitable car il élimine le temps de compilation. Toutefois, si les caractéristiques des données accédées par les requêtes de la procédure varient de manière significative lorsque différents paramètres sont passés, le résultat peut être très médiocre.

VOTRE DESCRIPTION DES RUNTIMES DES GAMMES DE DATE COURTES ET DES GAMMES LONGUELLES CONTRAITES PARFAIRE PARFAIRE. Je suppose que l'optimiseur de requêtes choisit différents index dans les deux scénarios.

Vous êtes sur la bonne voie pour vos solutions. WITH RECOMPILE Peut résoudre le paramètre reniflant dans certains cas, mais la recompilation est un coût élevé pour payer toutes les exécutions. OPTION(RECOMPILE) Sur les requêtes individuelles peut définitivement aider et est parfois la meilleure réponse, mais à nouveau, il s'agit à un coût élevé. OPTION(OPTIMIZE FOR UNKNOWN) est une autre possibilité, mais elle résout la question en fournissant un plan cohérent (mais peut toujours être horriblement inefficace).

Commencez par examiner ces articles, qui expliquent le paramètre reniflant beaucoup mieux que je ne le peux dans une réponse courte:

Ensuite, vérifiez les plans d'exécution de votre procédure, à la recherche de requêtes spécifiques qui varient le plus entre les exécutions. Essayez OPTION(RECOMPILE), OPTION(OPTIMIZE FOR UNKNOWN), ou Kimberly's sp_executesql Méthode sur celles-ci, plutôt que toute la procédure.

1
Ed Leighton-Dick