sql >> Base de Datos >  >> RDS >> Sqlserver

El rendimiento de las consultas de Entity Framework difiere mucho con la ejecución de SQL sin procesar

En esta respuesta, me estoy enfocando en la observación original:la consulta generada por EF es lenta, pero cuando la misma consulta se ejecuta en SSMS, es rápida.

Una posible explicación de este comportamiento es Análisis de parámetros .

Entonces, EF genera una consulta que tiene pocos parámetros. La primera vez que ejecuta esta consulta, el servidor crea un plan de ejecución para esta consulta utilizando valores de parámetros que estaban en vigor en la primera ejecución. Ese plan suele ser bastante bueno. Pero, más adelante, ejecuta la misma consulta EF utilizando otros valores para los parámetros. Es posible que para nuevos valores de parámetros el plan generado anteriormente no sea el óptimo y la consulta se vuelva lenta. El servidor sigue usando el plan anterior, porque sigue siendo la misma consulta, solo que los valores de los parámetros son diferentes.

Si en este momento toma el texto de la consulta e intenta ejecutarlo directamente en SSMS, el servidor creará un nuevo plan de ejecución, porque técnicamente no es la misma consulta que emite la aplicación EF. Incluso una diferencia de carácter es suficiente, cualquier cambio en la configuración de la sesión también es suficiente para que el servidor trate la consulta como una nueva. Como resultado, el servidor tiene dos planes para la misma consulta en su caché. El primer plan "lento" es lento para los nuevos valores de parámetros, porque originalmente se creó para diferentes valores de parámetros. El segundo plan "rápido" se crea para los valores de los parámetros actuales, por lo que es rápido.

El artículo Lento en la aplicación, rápido en SSMS por Erland Sommarskog explica esta y otras áreas relacionadas con muchos más detalles.

Hay varias formas de descartar planes almacenados en caché y obligar al servidor a regenerarlos. Cambiar la tabla o cambiar los índices de la tabla debería hacerlo; debería descartar todos los planes relacionados con esta tabla, tanto "lentos" como "rápidos". Luego ejecuta la consulta en la aplicación EF con nuevos valores de parámetros y obtiene un nuevo plan "rápido". Ejecuta la consulta en SSMS y obtiene un segundo plan "rápido" con nuevos valores de parámetros. El servidor todavía genera dos planes, pero ahora ambos planes son rápidos.

Otra variante es agregar OPTION(RECOMPILE) a la consulta Con esta opción el servidor no almacenaría en su caché el plan generado. Por lo tanto, cada vez que se ejecuta la consulta, el servidor usaría valores de parámetros reales para generar el plan que (cree) sería óptimo para los valores de parámetros dados. La desventaja es una sobrecarga adicional de la generación del plan.

Eso sí, el servidor aún podría elegir un plan "malo" con esta opción debido a estadísticas obsoletas, por ejemplo. Pero, al menos, la detección de parámetros no sería un problema.

Aquellos que se preguntan cómo agregar OPTION (RECOMPILE) sugerencia para la consulta generada por EF, eche un vistazo a esta respuesta:

https://stackoverflow.com/a/26762756/4116017