Tengo un procedimiento almacenado que se agota cada vez que se llama desde la aplicación web.
Encendí el Sql Profiler y rastreé las llamadas que se agotaron y finalmente descubrí estas cosas:
- Cuando se ejecutan las declaraciones desde dentro de MS SQL Management Studio, con los mismos argumentos (de hecho, copié la llamada al procedimiento desde el rastreo del perfil sql y la ejecuté): finaliza en un promedio de 5 ~ 6 segundos.
- Pero cuando se llama desde la aplicación web, tarda más de 30 segundos (en seguimiento), por lo que mi página web se agota para entonces.
Aparte del hecho de que mi aplicación web tiene su propio usuario, todo es igual (misma base de datos, conexión, servidor, etc.) También intenté ejecutar la consulta directamente en el estudio con el usuario de la aplicación web y no se necesitan más de 6 segundo.
¿Cómo averiguo lo que está pasando?
Supongo que no tiene nada que ver con el hecho de que usamos BLL> capas DAL o adaptadores de tabla, ya que el rastro muestra claramente que el retraso está en el procedimiento real. Eso es todo lo que puedo pensar.
EDITAR Descubrí en este enlace que ADO.NET se establece ARITHABORT
en verdadero, lo cual es bueno la mayor parte del tiempo, pero en algún momento esto sucede, y la solución with recompile
alternativa sugerida es agregar una opción al proceso almacenado. En mi caso, no funciona, pero sospecho que es algo muy similar a esto. ¿Alguien sabe qué más hace ADO.NET o dónde puedo encontrar la especificación?
fuente
Respuestas:
Me ha surgido un problema similar en el pasado, así que estoy ansioso por ver una solución a esta pregunta. El comentario de Aaron Bertrand sobre el OP provocó que la consulta se agotara cuando se ejecutaba desde la web, pero superrápido cuando se ejecutaba desde SSMS , y aunque la pregunta no es un duplicado, la respuesta puede muy bien aplicarse a su situación.
En esencia, parece que SQL Server puede tener un plan de ejecución en caché dañado. Está logrando un plan incorrecto con su servidor web, pero SSMS aterriza en un plan diferente ya que hay una configuración diferente en el indicador ARITHABORT (que de otro modo no tendría ningún impacto en su consulta particular / proceso almacenado).
Consulte ADO.NET llamando al procedimiento almacenado T-SQL que provoca una SqlTimeoutException para ver otro ejemplo, con una explicación y resolución más completas.
fuente
DBCC DROPCLEANBUFFERS
eDBCC FREEPROCCACHE
hizo el truco! Supongo que el plan de ejecución estaba dañado de alguna manera o no se actualizó. Dudo que sea una solución permanente, si pudiera corromperse una vez, podría volver a hacerlo. Así que sigo investigando las causas plausibles. Dado que la aplicación web ha vuelto a funcionar, no necesito sentir la presión. Muchas gracias.OPTIMIZE FOR
oOPTION(Recompile)
consultar sugerencias sobre las consultas que están causando problemas. Este artículo analiza el problema en profundidad. Si Entity Framework está generando sus consultas, esta publicación parece proporcionar una forma de agregar una sugerencia de consulta a sus consultas.También experimenté que las consultas se ejecutaban lentamente desde la web y rápidamente en SSMS y finalmente descubrí que el problema era algo llamado detección de parámetros.
La solución para mí fue cambiar todos los parámetros que se usan en el sproc a variables locales.
p.ej. cambio:
a:
Parece extraño, pero solucionó mi problema.
fuente
No al spam, pero como una solución útil para otros, nuestro sistema vio un alto grado de tiempos de espera.
Intenté configurar el procedimiento almacenado para que se recompile usando
sp_recompile
y esto resolvió el problema para el único SP.En última instancia, hubo una mayor cantidad de SP que agotaron el tiempo de espera, muchos de los cuales nunca lo habían hecho antes, mediante el uso,
DBCC DROPCLEANBUFFERS
yDBBC FREEPROCCACHE
la tasa de incidentes de tiempos de espera se ha desplomado significativamente; todavía hay casos aislados, algunos en los que sospecho que la regeneración del plan está tomando por un tiempo, y en algunos casos en los que los PE están realmente por debajo del rendimiento y necesitan una reevaluación.fuente
DBCC DROPCLEANBUFFERS
yDBCC FREEPROCCACHE
no hizo ninguna diferencia.¿Podría ser que algunas otras llamadas a la base de datos realizadas antes de que la aplicación web llame al SP mantiene una transacción abierta? Esa podría ser una razón para que este SP espere cuando lo llame la aplicación web. Digo aislar la llamada en la aplicación web (ponerla en una página nueva) para asegurarme de que alguna acción previa en la aplicación web esté causando este problema.
fuente
Simplemente recompilar el procedimiento almacenado (función de tabla en mi caso) funcionó para mí
fuente
como @Zane dijo que podría deberse a la detección de parámetros. Experimenté el mismo comportamiento y eché un vistazo al plan de ejecución del procedimiento y todas las declaraciones del sp en una fila (copié todas las declaraciones del procedimiento, declaré los parámetros como variables y asigné los mismos valores para la variable como los parámetros tenían). Sin embargo, el plan de ejecución se veía completamente diferente. La ejecución de sp tomó 3-4 segundos y las declaraciones en una fila con exactamente los mismos valores se devolvieron instantáneamente.
Después de buscar en Google, encontré una lectura interesante sobre ese comportamiento: ¿ Lento en la aplicación, Rápido en SSMS?
El problema era que tenía parámetros que podían dejarse como nulos y si se pasaban como nulos, se inicializarían con un valor predeterminado.
Después de que lo cambié a
funcionó como un encanto de nuevo.
fuente