sql-server - une - sql server historique des requetes




La requête expire lorsqu'elle est exécutée à partir du Web, mais très rapide lorsqu'elle est exécutée à partir de SSMS (5)

J'essaie de déboguer la source d'un délai d'attente SQL dans une application Web que je gère. J'ai le code source du code C # derrière, donc je sais exactement quel code est en cours d'exécution. J'ai débogué l'application jusqu'à la ligne qui exécute le code SQL qui expire, et je regarde la requête en cours d'exécution dans le profileur SQL.

Lorsque cette requête s'exécute à partir du Web, elle expire après 30 secondes. Cependant, lorsque je coupe / colle la requête exactement comme présenté dans Profiler, et que je la mets dans SSMS et l'exécute, elle revient presque instantanément. J'ai tracé le problème à ARITHABORT étant réglé sur OFF dans la connexion que le web utilise (c'est-à-dire, si j'active ARITHABORT OFF dans la session SSMS, il fonctionne pendant une longue période, et si je le rallume alors il court très rapidement). Cependant, en lisant la description de ARITHABORT, cela ne semble pas s'appliquer ... Je ne fais qu'un SELECT simple, et il n'y a AUCUN arithmétique en cours d'exécution du tout .. juste un seul INNER JOIN avec une condition WHERE:

Pourquoi ARITHABORT OFF provoquerait-il ce comportement dans ce contexte ?? Est-il possible de modifier le paramètre ARITHABORT pour cette connexion à partir de SSMS? J'utilise SQL Server 2008.


Donc votre code C # envoie une requête SQL ad hoc à SQL Server, en utilisant quelle méthode? Avez-vous envisagé d'utiliser une procédure stockée? Cela assurerait probablement la même performance (au moins dans le moteur), peu importe qui l'a appelé.

Pourquoi? Le paramètre ARITHABORT est l'un des éléments examinés par l'optimiseur lorsqu'il détermine comment exécuter votre requête (plus précisément, pour la correspondance de plan). Il est possible que le plan en cache ait le même paramètre que SSMS, donc il utilise le plan en cache, mais avec le paramètre opposé, votre code C # force une recompilation (ou peut-être que vous frappez un plan vraiment BAD dans le cache), peut certainement nuire à la performance dans beaucoup de cas.

Si vous appelez déjà une procédure stockée (vous n'avez pas envoyé votre requête, bien que je pense que vous le vouliez), vous pouvez essayer d'ajouter OPTION (RECOMPILE) à la ou aux requêtes incriminées dans la procédure stockée. Cela signifie que ces instructions seront toujours recompilées, mais cela pourrait empêcher l'utilisation du mauvais plan que vous semblez atteindre. Une autre option consiste à s'assurer que lorsque la procédure stockée est compilée, le lot est exécuté avec SET ARITHABORT ON.

Enfin, vous semblez vous demander comment vous pouvez modifier le paramètre ARITHABORT dans SSMS. Je pense que ce que vous vouliez demander, c'est comment vous pouvez forcer le réglage ARITHABORT dans votre code. Si vous décidez de continuer à envoyer un SQL ad hoc à partir de votre application C #, vous pouvez bien sûr envoyer une commande sous forme de texte avec plusieurs instructions séparées par des points-virgules, par exemple:

SET ARITHABORT ON; SELECT ...

Pour plus d'informations sur les raisons de ce problème, consultez l'excellent article d'Erland Sommarskog:


J'ai déjà eu ce problème plusieurs fois, mais si vous avez une procédure stockée avec le même problème, abandonner et recréer le proc stocké va résoudre le problème.

C'est ce qu'on appelle le reniflage des paramètres. Vous devez toujours localiser les paramètres dans la proc stockée pour éviter ce problème dans le futur.

Je comprends que ce n'est peut-être pas ce que l'affiche originale veut mais qu'elle pourrait aider quelqu'un ayant le même problème.


J'ai le même problème en essayant d'appeler SP à partir de SMSS il a fallu 2 secondes, tandis que de la webapp (ASP.NET), il a fallu environ 3 minutes.

J'ai essayé toutes les solutions suggérées sp_recompile , DBCC FREEPROCCACHE et DBCC DROPCLEANBUFFERS mais rien n'a résolu mon problème, mais quand essayé le reniflage de paramètre il a fait l'affaire, et a fonctionné très bien.


Si vous pouvez changer votre code pour fixer le reniflage de paramètre optimisez pour l'indice inconnu est votre meilleure option. Si vous ne pouvez pas changer votre code, la meilleure option est exec sp_recompile 'nom de proc' qui forcera seulement un proc stocké à obtenir un nouveau plan d'exécution. Laisser tomber et recréer un proc aurait un effet similaire mais pourrait causer des erreurs si quelqu'un essayait d'exécuter le proc pendant que vous le laissiez tomber. DBCC FREEPROCCACHE supprime tous vos plans en cache, ce qui peut faire des ravages sur votre système jusqu'à et y compris causer beaucoup de délais dans un environnement de production de transactions lourdes. Définir arithabort n'est pas une solution au problème, mais est un outil utile pour découvrir si le reniflage de paramètre est le problème.


Cette réponse inclut un moyen de résoudre ce problème:

En exécutant les commandes suivantes en tant qu'administrateur sur la base de données, toutes les requêtes s'exécutent comme prévu, quel que soit le paramètre ARITHABORT.

 DBCC DROPCLEANBUFFERS
 DBCC FREEPROCCACHE

Mettre à jour

Il semble que la plupart des gens finissent par avoir ce problème se produisent très rarement, et la technique ci-dessus est un correctif ponctuel décent. Mais si une requête spécifique présente ce problème plus d'une fois, une solution plus à long terme à ce problème consisterait à utiliser des conseils de requête tels que OPTIMIZE FOR et OPTION(Recompile) , comme décrit dans cet article .







arithabort