Entity Framework consulta lenta, pero el mismo SQL en SqlQuery es rápido


Estoy viendo algunos perf realmente extraño relacionado con una consulta muy simple utilizando el Código de Entity Framework-Primero con.NET framework versión 4. La consulta LINQ2Entities se ve así:

 context.MyTables.Where(m => m.SomeStringProp == stringVar);

Esto tarda más de 3000 milisegundos en 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);

Entonces, exactamente lo mismo SQL, las entidades resultantes son de seguimiento de cambios en ambos casos, pero la diferencia perf salvaje entre los dos. ¿Qué pasa?

Author: Michael Sandler, 2013-04-02

7 answers

Lo encontré. Resulta que es un problema de tipos de datos SQL. La columna SomeStringProp en la base de datos era un varchar, pero EF asume que los tipos de cadenas.NET son nvarchar. El proceso de traducción resultante durante la consulta para que la BD haga la comparación es lo que lleva mucho tiempo. Creo que EF Prof me estaba desviando un poco aquí, 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'

Así que la solución resultante es anotar el modelo primero en código, indicando tipo de datos SQL correcto:

public class MyTable
{
    ...

    [Column(TypeName="varchar")]
    public string SomeStringProp { get; set; }

    ...
}
 65
Author: Brian Sullivan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-02 19:39:05

La razón de ralentizar mis consultas realizadas en EF fue comparar escalares no nullables con escalares nullables:

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. Tomó sólo 50ms para completar. Es posible que sea un error en EF.

 31
Author: cryss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-07 10:47:01

Si está utilizando la asignación fluent, 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

 6
Author: Matt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-25 20:36:01

Tuve el mismo problema (la consulta es rápida cuando se ejecuta desde SQL Manager) pero cuando se ejecuta desde EF el tiempo de espera expira.

Resulta que la entidad (que fue creada a partir de la vista) tenía claves de entidad incorrectas. Así que la entidad tenía filas duplicadas con las mismas claves, y supongo que tenía que hacer agrupación en el fondo.

 2
Author: Vladimir Gedgafov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-12 18:01:28

También me encontré con esto con una consulta ef compleja. Una solución para mí que redujo una consulta ef de 6 segundos a la consulta sql secundaria que generó fue desactivar la carga lenta.

Para encontrar esta configuración (ef 6) vaya a .edmx y busque en las propiedades - > Generación de código - > Carga lenta habilitada. Establecer en false.

Mejora masiva en el rendimiento para mí.

 2
Author: user2622095,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-30 11:40:14

Puede utilizar los siguientes trucos para fijar sus consultas -

  1. Establezca ctx.Configuration.ProxyCreationEnabled en false justo antes de obtener el contexto.
  2. También, .Select(c => new {c.someproperty}) obtendrá solo los datos requeridos y no todo el grupo.

Hazme saber si esto ayudó.

 1
Author: Rajesh Panda,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-16 20:30:43

Yo también tuve este problema. Resulta que el culpable en mi caso fue SQL-Server parámetro sniffing .

La primera pista de que mi problema se debió de hecho a la detección de parámetros fue que ejecutar la consulta con "set arithabort off" o "set arithabort on" produjo tiempos de ejecución drásticamente diferentes en Management Studio. Esto es porque ADO.NET por defecto usa " set arithabort off "y Management Studio por defecto usa"set arithabort on". La caché del plan de consultas mantiene diferentes planes dependiendo de este parámetro.

Deshabilité el almacenamiento en caché del plan de consultas para la consulta, con la solución que puede encontrar aquí.

 1
Author: Oskar Sjöberg,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-23 10:35:09