2011-02-08 30 views
19

tengo una tabla:¿Cuándo debería usar CompiledQuery?

-- Tag 

ID | Name 
----------- 
1 | c# 
2 | linq 
3 | entity-framework 

tengo una clase que tendrán los siguientes métodos:

IEnumerable<Tag> GetAll(); 
IEnumerable<Tag> GetByName(); 

¿Debo usar una consulta compilada en este caso?

static readonly Func<Entities, IEnumerable<Tag>> AllTags = 
    CompiledQuery.Compile<Entities, IEnumerable<Tag>> 
    (
     e => e.Tags 
    ); 

Entonces mi método GetByName sería:

IEnumerable<Tag> GetByName(string name) 
{ 
    using (var db = new Entities()) 
    { 
     return AllTags(db).Where(t => t.Name.Contains(name)).ToList(); 
    } 
} 

que genera un SELECT ID, Name FROM Tag y ejecutar Where en el código. ¿O debería evitar CompiledQuery en este caso?

Básicamente, quiero saber cuándo debo usar las consultas compiladas. Además, en un sitio web, se compilan solo una vez para toda la aplicación.

+0

El ejemplo que proporcione fallará en el tiempo de ejecución (debe pasar el contexto, y no puede usar 'Func <>' sin 'Expresión <>'. Además, compilando aún más la consulta ('Donde (t = > ... ')" descompila "el resultado. Pero la pregunta es válida. –

+1

En .NET 4.5 se realizará automáticamente. Consulte" Entidad Framework 5: control de la compilación automática de consultas "http://blogs.msdn.com/ b/stuartleeks/archive/2012/06/12/entity-framework-5-controlling-automatic-query-compilation.aspx) –

Respuesta

26

se debe utilizar un CompiledQuery cuando todas las condiciones siguientes son verdaderas:

  • La consulta se ejecutará más de una vez, variando únicamente por los valores de los parámetros.
  • La consulta es suficientemente complejo que el costo de la evaluación de la expresión y la generación de vistas es "significativo" (ensayo y error)
  • No está utilizando una característica LINQ como IEnumerable<T>.Contains() que no funcionará con CompiledQuery.
  • Ya ha simplificado la consulta, lo que ofrece un mayor beneficio de rendimiento, cuando es posible.
  • No tiene la intención de componer los resultados de la consulta (por ejemplo, restringir o proyecto), lo que tiene el efecto de "descompilarlo".

CompiledQuery hace su trabajo la primera vez que se ejecuta una consulta. No da ningún beneficio para la primera ejecución. Al igual que cualquier ajuste de rendimiento, generalmente evítelo hasta que esté seguro de que está arreglando un punto de acceso de rendimiento real.

2012 Actualización: EF 5 hará esto automáticamente (vea "Entity Framework 5: Controlling automatic query compilation"). Así que agrega "No estás usando EF 5" a la lista anterior.

1

las consultas compiladas son más útiles con las consultas de linq con árboles de expresiones grandes que dicen consultas complejas para obtener un rendimiento sobre el desarrollo del árbol de expresiones una y otra vez al reutilizar la consulta. en su caso, supongo que ahorrará muy poco tiempo.

+0

'SELECT ID, Name FROM Tags' frente a' SELECT ID, Name FROM Tags WHERE Name LIKE '% nombre% ''en una tabla de filas 1M, la consulta compilada obtendrá rendimiento ejecutando la primera selección y luego filtrará los resultados en el código? – BrunoLM

+0

nada, debe filtrar los registros en el nivel DB no en el código. Esto será un error al filtrar el código. La consulta compilada solo significa que la exp el árbol de la ressión está precompilado. La segunda consulta es el camino a seguir –

0

Las consultas compiladas ofrecen una mejora en el rendimiento, pero no es enorme. Si tiene consultas complejas, prefiero ir con un procedimiento almacenado o una vista, si es posible; dejar que la base de datos lo haga podría ser un mejor enfoque.

+1

Bueno, nuestras pruebas muestran que si reutiliza la consulta puede agregar un retraso notable bastante rápido debido al tiempo de compilación. Especialmente si tienes muchas consultas diferentes. –

0

Las consultas compiladas se compilan cuando se compila la aplicación y cada vez que reutiliza una consulta con frecuencia o es compleja, debe probar las consultas compiladas para acelerar la ejecución.

Pero no me atrevería a hacerlo en todas las consultas, ya que es un poco más código para escribir y para consultas sencillas puede que no valga la pena.

Pero para obtener el máximo rendimiento también debe evaluar los procedimientos almacenados en los que realiza todo el procesamiento en el servidor de la base de datos, incluso si Linq intenta llevar la mayor cantidad posible de trabajo a la base de datos, tendrá situaciones donde un procedimiento almacenado se más rápido.

+4

No, 'CompiledQuery' se compila en el tiempo de ejecución, justo antes de la primera ejecución. –

6

Las consultas compiladas le ahorran tiempo, lo que se utilizaría para generar árboles de expresiones. Si la consulta se usa con frecuencia y guardará la consulta compilada, definitivamente debe usarla. Tuve muchos casos en los que el análisis de consultas llevó más tiempo que el viaje de ida y vuelta real a la base de datos.

En su caso, si está seguro de que generaría SELECT ID, Name FROM Tag sin que el caso WHERE (cosa que dudo, ya que su función debe devolver AllQueriesIQueryable y la consulta real debe hacerse sólo después de llamar ToList) - que no debería usarlo

Como alguien ya ha mencionado, en las tablas más grandes SELECT * FROM [someBigTable] tomaría mucho tiempo y pasaría incluso más tiempo filtrando eso en el lado del cliente. Por lo tanto, debe asegurarse de que su filtrado se realice en el lado de la base de datos, sin importar si está utilizando consultas compiladas o no.

Cuestiones relacionadas