24

Estoy teniendo algunos problemas importantes de rendimiento con consultas SQL simples generadas por Entity Framework (4.2) ejecutándose en SQL Server 2008 R2. En algunas situaciones (pero no todos), EF utiliza la siguiente sintaxis:Entity Framework 4.2 exec sp_executesql no utiliza índices (detección de parámetros)

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE', @param1... 

En otras situaciones es simplemente ejecuta el SQL crudo con los parámetros proporcionados al horno en la consulta. El problema que encuentro es que las consultas ejecutadas con sp_executesql ignoran todos los índices en mis tablas de destino, lo que resulta en una consulta de rendimiento extremadamente pobre (confirmada al examinar el plan de ejecución en SSMS).

Después de un poco de investigación, parece que el problema podría ser causado por el "olfato de parámetros". Si añado la indirecta OPCIÓN (RECOMPILE) consulta de este modo:

exec sp_executesql 'DYNAMIC-SQL-QUERY-HERE OPTION(RECOMPILE)', @param1... 

Los índices en las tablas de destino se utilizan y la consulta se ejecuta de forma extremadamente rápida. También intenté alternar en el indicador de rastreo utilizado para desactivar el rastreo de parámetros (4136) en la instancia de la base de datos (http://support.microsoft.com/kb/980653), sin embargo, esto no pareció tener ningún efecto en absoluto.

Esto me deja con algunas preguntas:

  1. todos modos hay que añadir el toque OPCIÓN (RECOMPILE) consulta al SQL generado por Entity Framework?
  2. ¿Hay alguna forma de evitar que Entity Framework use exec sp_executesql, y simplemente ejecute el SQL sin formato?
  3. ¿Alguien más tiene este problema? ¿Alguna otra pista/sugerencia?

Información adicional:

  1. hice reiniciar la instancia de base de datos a través de SSMS, sin embargo, voy a tratar de reiniciar el servicio desde la consola de administración de servicios.
  2. Parametrización se establece en simples (is_parameterization_forced: 0)
  3. Optimizar para cargas de trabajo ad hoc tiene los siguientes valores
    • valor: 0
    • mínimo: 0
    • máxima: 1
    • value_in_use: 0
    • is_dynamic: 1
    • is_advanced: 1

Debo mencionar también que si reinicio el servicio de SQL Server a través de la consola de gestión del servicio DESPUÉS de habilitar el indicador de traza 4136 con la siguiente secuencia de comandos, parece borrar la marca de traza ... quizás debería estar haciendo esto de manera diferente ...

DBCC TRACEON(4136,-1) 
+1

No puedo responder nada sobre EF (lo siento, nunca lo he tocado), pero tengo otras preguntas que debe responder en su pregunta: ¿Reinició el servicio después de configurar el indicador de seguimiento? ¿Cuál es su configuración en el nivel de la base de datos para la parametrización (simple o forzada, consulte 'sys.databases.is_parameterization_forced')? ¿Cuál es la configuración sp_configure para "optimizar para cargas de trabajo ad hoc"? Desafortunadamente, si no recuerdo mal, EF creará dos planes diferentes para parámetros como N'foo 'y N'blat', porque son longitudes diferentes. –

+0

¡Mis disculpas por la respuesta tardía y gracias por su rápido comentario! He agregado la información adicional a la publicación original. – mindlessgoods

+0

Así que volvería a probar las pruebas con (a) parametrización establecida en forzada (b) optimize para cargas de trabajo ad hoc establecidas en 1 y (c) ambas. Es bastante probable que (b) ayude a este escenario pero (a) también podría ayudar. Confieso que no probé mucho con (a) pero (b) he ayudado con todas las cargas de trabajo ad hoc que he probado. –

Respuesta

5

en este punto, recomiendo:


Establecer la función para optimizar las cargas de trabajo ad hoc valor a true.

EXEC sp_configure 'show advanced', 1; 
GO 
RECONFIGURE WITH OVERRIDE; 
GO 
EXEC sp_configure 'optimize for ad hoc', 1; 
GO 
RECONFIGURE WITH OVERRIDE 
GO 
EXEC sp_configure 'show advanced', 0; 
GO 
RECONFIGURE WITH OVERRIDE; 
GO 

Si después de un tiempo no parece haber ayudado a esta configuración, sólo entonces habría que probar el apoyo adicional de la marca de seguimiento. Estos generalmente se reservan como último recurso. Establezca la marca de seguimiento utilizando la línea de comando a través del Administrador de configuración de SQL Server, en lugar de en una ventana de consulta y utilizando el indicador global. Ver http://msdn.microsoft.com/en-us/library/ms187329.aspx

6

tl; dr

update statistics


Tuvimos una consulta delete con un parámetro (la clave principal) que se llevó a ~ 7 segundos para completar cuando se llama a través de EF y sp_executesql. Al ejecutar la consulta manualmente, con el parámetro incrustado en el primer argumento en sp_executesql, la consulta se ejecutó rápidamente (~ 0.2 segundos). Agregar option (recompile) también funcionó. Por supuesto, esas dos soluciones no están disponibles para nosotros ya que estábamos usando EF.

Probablemente debido a las limitaciones de clave externa en cascada, el plan de ejecución para la consulta de larga ejecución fue, uhmm ..., enorme. Cuando miré el plan de ejecución en SSMS noté que las flechas entre los diferentes pasos en algunos casos eran más anchas que otras, lo que posiblemente indica que SQL Server tuvo problemas para tomar las decisiones correctas. Eso me llevó a pensar en estadísticas. Miré los pasos en el plan de ejecución para ver qué tabla estaba involucrada en los pasos sospechosos. Luego ejecuté update statistics Table para esa tabla. Luego volví a ejecutar la consulta incorrecta. Y volví a ejecutarlo de nuevo. Y otra vez solo para estar seguro. Funcionó. Nuestro perf fue vuelto a la normalidad. (Todavía algo peor que el rendimiento no sp_executesql, pero bueno!)

Resultó que esto era solo un problema en nuestro entorno de desarrollo. (Y fue un gran problema porque hizo que nuestras pruebas de integración durasen para siempre.) En nuestro entorno de producción, teníamos un trabajo en ejecución que actualizaba todas las estadísticas de forma regular.

+1

Esto funciona cuando funciona, pero * no * siempre funciona, aún deja "una buena manera" de recibir sugerencias de SQL Server de EF. – user2864740

Cuestiones relacionadas