J'ai stocké une procédure qui expire incroyablement à chaque fois qu'elle est appelée à partir de l'application Web.
J'ai lancé le Sql Profiler et tracé les appels qui expirent et finalement découvert ces choses:
- Lors de l'exécution des instructions à partir du MS SQL Management Studio, avec les mêmes arguments (en fait, j'ai copié l'appel de procédure à partir de la trace de profil SQL et l'ai exécuté): Il se termine en 5 ~ 6 secondes en moyenne.
- Mais lorsqu'il est appelé à partir d'une application Web, cela prend plus de 30 secondes (dans la trace), donc ma page Web expire réellement d'ici là.
Outre le fait que mon application Web a son propre utilisateur, tout est identique (même base de données, connexion, serveur, etc.) J'ai également essayé d'exécuter la requête directement dans le studio avec l'utilisateur de l'application Web et cela ne prend pas plus de 6 seconde.
Comment savoir ce qui se passe?
Je suppose que cela n'a rien à voir avec le fait que nous utilisons des couches BLL> DAL ou des adaptateurs de table car la trace montre clairement que le retard est dans la procédure réelle. C'est tout ce que je peux penser.
EDIT J'ai découvert dans ce lien qu'ADO.NET définit ARITHABORT
sur true - ce qui est bon pour la plupart du temps, mais cela se produit parfois, et la with recompile
solution de contournement suggérée consiste à ajouter une option au processus stocké. Dans mon cas, cela ne fonctionne pas mais je soupçonne que c'est quelque chose de très similaire à cela. Tout le monde sait ce que ADO.NET fait d'autre ou où je peux trouver les spécifications?
la source
Réponses:
J'ai eu un problème similaire dans le passé, donc je suis impatient de voir une solution à cette question. Le commentaire d'Aaron Bertrand sur l'OP a conduit à l' expiration de la requête lorsqu'elle est exécutée à partir du Web, mais ultra-rapide lorsqu'elle est exécutée à partir de SSMS , et bien que la question ne soit pas un double, la réponse peut très bien s'appliquer à votre situation.
En substance, il semble que SQL Server puisse avoir un plan d'exécution mis en cache corrompu. Vous rencontrez le mauvais plan avec votre serveur Web, mais SSMS atterrit sur un plan différent car il existe un paramètre différent sur l'indicateur ARITHABORT (qui autrement n'aurait aucun impact sur votre requête / procédure stockée particulière).
Voir ADO.NET appeler une procédure stockée T-SQL provoque une exception SqlTimeoutException pour un autre exemple, avec une explication et une résolution plus complètes.
la source
DBCC DROPCLEANBUFFERS
et aDBCC FREEPROCCACHE
fait l'affaire! Je suppose que le plan d'exécution était en quelque sorte corrompu ou non mis à jour. Je doute que ce soit une solution permanente, s'il pouvait être corrompu une fois, il pourrait le faire à nouveau. Je suis donc toujours à la recherche des causes plausibles. Depuis que l'application Web est de nouveau au travail, je n'ai pas besoin de ressentir la pression. Merci beaucoup.OPTIMIZE FOR
ou d'OPTION(Recompile)
interroger des indices sur les requêtes qui posent des problèmes. Cet article décrit le problème en profondeur. Si Entity Framework génère vos requêtes, cet article semble fournir un moyen d'ajouter un indice de requête à vos requêtes.J'ai également constaté que les requêtes s'exécutaient lentement à partir du Web et rapidement dans SSMS et j'ai finalement découvert que le problème était quelque chose appelé le reniflage de paramètres.
Le correctif pour moi était de changer tous les paramètres utilisés dans le sproc en variables locales.
par exemple. changement:
à:
Cela semble étrange, mais cela a résolu mon problème.
la source
Pas pour le spam, mais comme solution, espérons-le, utile pour les autres, notre système a connu un degré élevé de délais d'attente.
J'ai essayé de définir la procédure stockée à recompiler à l'aide de
sp_recompile
et cela a résolu le problème pour le seul SP.En fin de compte, il y avait un plus grand nombre de SP qui expiraient, dont beaucoup ne l'avaient jamais fait auparavant, en utilisant
DBCC DROPCLEANBUFFERS
etDBBC FREEPROCCACHE
le taux d'incident des délais d'expiration a considérablement chuté - il y a encore des événements isolés, certains où je soupçonne que la régénération du plan prend un certain temps, et d'autres où les SP sont vraiment sous-performants et doivent être réévalués.la source
DBCC DROPCLEANBUFFERS
etDBCC FREEPROCCACHE
n'a fait aucune différence.Se pourrait-il que certains autres appels de base de données effectués avant que l'application Web appelle le SP maintiennent une transaction ouverte? Cela pourrait être une raison pour que ce SP attende lorsqu'il est appelé par l'application Web. Je dis isoler l'appel dans l'application Web (placez-le sur une nouvelle page) pour vous assurer qu'une action préalable dans l'application Web est à l'origine de ce problème.
la source
Recompiler simplement la procédure stockée (fonction de table dans mon cas) a fonctionné pour moi
la source
comme @Zane l'a dit, cela pourrait être dû au reniflage de paramètres. J'ai vécu le même comportement et j'ai jeté un coup d'œil au plan d'exécution de la procédure et à toutes les instructions du sp dans une ligne (copié toutes les instructions de la procédure, déclaré les paramètres en tant que variables et attribué les mêmes valeurs pour la variable que les paramètres avaient). Cependant, le plan d'exécution était complètement différent. L'exécution de sp a pris 3-4 secondes et les instructions dans une ligne avec exactement les mêmes valeurs ont été instantanément renvoyées.
Après quelques recherches sur Google, j'ai trouvé une lecture intéressante sur ce comportement: lent dans l'application, rapide dans SSMS?
Le problème était que j'avais des paramètres qui pouvaient être laissés nuls et s'ils étaient passés comme null, ils seraient initialisés avec une valeur par défaut.
Après l'avoir changé en
cela fonctionna à nouveau comme un charme.
la source