performance - practices - La consulta de Entity Framework es lenta, pero el mismo SQL en SqlQuery es rĂ¡pido
entity framework precompiled query (7)
La razón de desacelerar mis consultas realizadas en EF fue la comparación de escalares no nulables con escalas nulables:
long? userId = 10; // nullable scalar
db.Table<Document>().Where(x => x.User.Id == userId).ToList() // or userId.Value
^^^^^^^^^ ^^^^^^
Type: long Type: long?
Esa consulta tomó 35 segundos. Pero una pequeña refactorización como esa:
long? userId = 10;
long userIdValue = userId.Value; // I''ve done that only for the presentation pursposes
db.Table<Document>().Where(x => x.User.Id == userIdValue).ToList()
^^^^^^^^^ ^^^^^^^^^^^
Type: long Type: long
da resultados increíbles Solo tomó 50ms para completar. Es posible que sea un error en EF.
Estoy viendo un rendimiento realmente extraño relacionado con una consulta muy simple usando Entity Framework Code-First con .NET framework versión 4. La consulta de LINQ2Entities se ve así:
context.MyTables.Where(m => m.SomeStringProp == stringVar);
Esto toma más de 3000 milisegundos para ejecutarse. El SQL generado parece muy simple:
SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
...
FROM [MyTable] as [Extent1]
WHERE [Extent1].[SomeStringProp] = ''1234567890''
Esta consulta se ejecuta casi instantáneamente cuando se ejecuta a través de Management Studio. Cuando cambio el código C # para usar la función SqlQuery, se ejecuta en 5-10 milisegundos:
context.MyTables.SqlQuery("SELECT [Extent1].[ID] ... WHERE [Extent1].[SomeStringProp] = @param", stringVar);
Por lo tanto, exactamente el mismo SQL, las entidades resultantes se cambian de seguimiento en ambos casos, pero la diferencia de rendimiento salvaje entre los dos. ¿Lo que da?
Lo encontré. Resulta que es un problema de tipos de datos SQL. La columna SomeStringProp
en la base de datos era varchar, pero EF supone que los tipos de cadena .NET son nvarchars. El proceso de traducción resultante durante la consulta de DB para hacer la comparación es lo que lleva mucho tiempo. Creo que EF Prof me estaba llevando por mal camino un poco, una representación más precisa de la consulta que se está ejecutando sería la siguiente:
SELECT [Extent1].[ID], [Extent1].[SomeStringProp], [Extent1].[SomeOtherProp],
...
FROM [MyTable] as [Extent1]
WHERE [Extent1].[SomeStringProp] = N''1234567890''
Entonces la solución resultante es anotar el modelo de primer código, que indica el tipo de datos de SQL correcto:
public class MyTable
{
...
[Column(TypeName="varchar")]
public string SomeStringProp { get; set; }
...
}
Puede usar los siguientes trucos para ajustar sus consultas:
- Establezca
ctx.Configuration.ProxyCreationEnabled
enfalse
justo antes de obtener el contexto. - Además,
.Select(c => new {c.someproperty})
solo obtendrá los datos requeridos y no todo el grupo.
Hagame saber si esto fue de utilidad.
Si está utilizando la asignación fluida, puede usar IsUnicode(false)
como parte de la configuración para obtener el mismo efecto:
http://msdn.microsoft.com/en-us/data/jj591617.aspx#1.9
http://msdn.microsoft.com/en-us/library/gg696416%28v=vs.103%29.aspx
También encontré esto con una consulta compleja de ef. Una solución para mí que redujo una segunda consulta de 6 segundos a la segunda consulta sql que generó fue desactivar la carga diferida.
Para encontrar esta configuración (ef 6), vaya al archivo .edmx y busque en Propiedades -> Generación de código -> Carga lenta habilitada. Establecer en falso.
Mejora masiva en el rendimiento para mí.
Tuve el mismo problema (la consulta es rápida cuando se ejecuta desde el administrador de SQL) pero cuando se ejecuta desde EF, el tiempo de espera expira.
Resulta que la entidad (que se creó a partir de la vista) tenía claves de entidad incorrectas. Entonces la entidad tenía filas duplicadas con las mismas claves, y supongo que tenía que agruparlas en el fondo.
Yo tuve este problema también. Resulta que el culpable en mi caso era el olfateo de los parámetros del Servidor SQL. Leer más
La primera pista de que mi problema se debía al olfateo de parámetros fue que al ejecutar la consulta con "set arithabort off" o "set arithabort on" se obtuvieron tiempos de ejecución drásticamente diferentes en Management Studio. Esto se debe a que ADO.NET utiliza de forma predeterminada "set arithabort off" y Management Studio establece de manera predeterminada "set arithabort on" y la caché del plan de consulta mantiene diferentes planes según este parámetro.
Inhabilité el almacenamiento en caché del plan de consulta para la consulta, con la solución que puede encontrar here .