Como el título sugiere que tengo un problema con la primera consulta en una base de datos de SQL Server con Entity Framework.Entidad Framework - Primera consulta lenta
He intentado buscar una respuesta en diferentes sitios pero nadie parece tener una solución para esto.
Estoy cargando bastantes filas de la base de datos que incluyen dos relaciones 0-many.
Las pruebas se realizaron en Visual Studio 2010 utilizando el modelo Entity Framework 4.0 y el generador POCO (no hay mucha diferencia en los tiempos entre entidades normales y objetos POCO). También utilicé la Plantilla de Vistas T4 para precompilar las vistas.
La base de datos fue en SQL Server 2008.
Lo que me gustaría saber es por qué la primera consulta es taaan mucho más lenta que cualquier consulta secundarias.
También quiero saber si se puede hacer algo para aumentar la velocidad de la primera consulta hasta un punto en el que esté dentro de los límites aceptables.
Esta es una gran consulta y podemos obtener otras consultas que son aún mayores y es comprensible que puedan ser un poco lentas, pero 30 segundos es demasiado lento para que el usuario espere, especialmente cuando los conjuntos de datos pueden obtener los mismos datos mucho más rápido
He hecho algunas pruebas de tiempo para tratar de averiguar dónde está el problema y me sorprendió un poco ver que parece que es el SQL Server el que tarda en la primera consulta.
sincronizaciones fue la siguiente:
.NET aplicación de prueba:
- primera consulta: 29,6 segundos
- segunda consulta: 3,2 segundos
SQL Profiler:
- First Qu ery: 27 segundos
- segunda consulta: 3,2 segundos
SQL Server ventana Query
- primera consulta: 8 segundos
- segunda consulta: 4 segundos
Timings en la aplicación se midió con la clase Stopwatch
. Solo se midió la consulta y se utilizó .ToList()
para ejecutar la consulta.
Las temporizaciones en SQL Server Profiler son para las mismas consultas que se ejecutaron en la aplicación que muestran que la aplicación solo utiliza aproximadamente 2,6 segundos para completar datos en los objetos.
Los últimos 27 segundos se utilizan para ejecutar la consulta en SQL Server.
En cuanto a la consulta secundaria, los tiempos son los mismos tanto para la aplicación como para el servidor SQL, pero la ejecución de la consulta es mucho más rápida esta vez.
Entiendo por qué la aplicación no utiliza ningún momento porque no hay nuevas filas que deban convertirse en objetos, pero ¿por qué la consulta es mucho más rápida ?, habría esperado unos segundos debido a los planes de ejecución, pero no 24 segundos.
Solo para fines de prueba copié el SQL que genera Entity Framework y abrí una nueva ventana de consulta con una conexión separada y ejecuté la consulta en ella.
Como puede ver, tarda 8 segundos para la primera consulta y 4 segundos para la segunda.
Espero que alguien tenga algunas sugerencias.
ps. Me disculpo por el muro de texto :)
Editar 19-10-2010:
Hice una prueba ayer que parece ser compatible con que las filas se devuelvan de forma secuencial. Lo que significa que cuando se devuelve una fila de la base de datos se materializa inmediatamente (si no existe en el contexto), se devuelve la siguiente fila y así sucesivamente.
Es por eso que parece que la consulta lleva mucho tiempo en el servidor de la base de datos porque el tiempo de materialización se incluye en los tiempos del perfilador de SQL Server.
No creo que sea un caso de lectura de SQL Server desde el disco duro. La consulta lenta ocurre cada vez que hay una "primera consulta" en EF.
ex.
- Ejecutar la primera consulta con EF, la instrucción SQL es más lento que cualquier consulta secundaria
- Desechar el contexto/repositorio
- Crear un nuevo contexto
- ejecutar la misma consulta que antes (de nuevo la primera la consulta es lenta y también la instrucción SQL)
Es casi como que EF envía algunas opciones junto con la primera consulta que hace que el servidor sea lento.
En cuanto a la compilación de consultas, ya que recuerdo que la consulta se compila la primera vez que se utiliza, lo que significa que la primera consulta tardará aún más en ejecutarse.
Las consultas secundarias serían más rápidas, pero la velocidad en las consultas secundarias no es el problema.
También hice una prueba donde creé una consulta compilada como estática para que se compilara para todos los contextos que se crearon.
Luego creé un contexto, ejecuté la consulta, destruí el contexto y creé uno nuevo y ejecuté la misma consulta una vez más.
La diferencia no fue tan grande, solo unos segundos y la primera vez que ejecuté la consulta, me tomó todo el tiempo posible sin precompilarla.
En cuanto a la generación de vistas, ya lo implementamos utilizando plantillas T4.
¿La respuesta es realmente que EF solo funciona si no se hace nada más que las consultas más simples que devuelven solo una cantidad relativamente pequeña de datos?
Disculpa la respuesta tardía. No creo que sea un caso de lectura de SQL Server desde el disco duro. La consulta lenta ocurre cada vez que hay una "primera consulta" en EF. P.ej. 1) Ejecute la primera consulta con EF, la instrucción SQL es más lenta que cualquier consulta secundaria. 2) Eliminar el contexto/repositorio. 3) Crea un nuevo contexto. 4) Ejecuta la misma consulta que antes. (de nuevo, la primera consulta es lenta y también lo es la declaración de SQL) Es casi como que EF envía algunas opciones junto con la primera consulta que hace que el servidor sea lento. –
En cuanto a la compilación de consultas, creo que la consulta se compila la primera vez que se utiliza, es decir, la primera consulta tardará aún más en ejecutarse. Las consultas secundarias serían más rápidas, pero la velocidad en las consultas secundarias no es el problema. También realicé una prueba donde creé una consulta compilada estática para que se compilara para todos los contextos que se crearon. Luego creé un contexto, ejecuté la consulta, eliminé el contexto, creé uno nuevo y ejecuté la consulta nuevamente. La diferencia no fue tan grande, solo unos pocos segundos, y la primera vez que ejecuté la consulta, me tomó todo el tiempo sin precompilarla. –
En cuanto a View Generation, ya implementamos esto usando plantillas T4. ¿La respuesta es realmente que EF solo funciona si no haces nada más que las consultas más simples que devuelven solo una cantidad relativamente pequeña de datos? –