2011-02-08 14 views
19

Ho una tabella:Quando dovrei usare CompiledQuery?

-- Tag 

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

ho una classe che avrà i seguenti metodi:

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

Dovrei usare una query compilata in questo caso?

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

Poi il mio metodo GetByName sarebbe:

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

che genera un SELECT ID, Name FROM Tag ed eseguire Where sul codice. O dovrei evitare CompiledQuery in questo caso?

Fondamentalmente voglio sapere quando dovrei usare le query compilate. Inoltre, su un sito Web vengono compilati una sola volta per l'intera applicazione?

+0

L'esempio fornito non funzionerà in fase di esecuzione (è necessario passare il contesto e non è possibile utilizzare "Func <>" senza "Expression <>". Inoltre, è necessario comporre la query ('Where (t = > ... ')" decompila "il risultato, ma la domanda è valida –

+1

In .net 4.5 verrà eseguita automaticamente Vedere" Entity Framework 5: Controllo della compilazione automatica delle query "http://blogs.msdn.com/ b/stuartleeks/archive/2012/06/12/entity-framework-5-controlling-automatic-query-compilation.aspx) –

risposta

26

è necessario utilizzare un CompiledQuery quando tutte le seguenti condizioni:

  • La query verrà eseguita più di una volta, variando solo per i valori dei parametri.
  • la query è abbastanza complessa che il costo di valutazione delle espressioni e vista generazione è "significativo" (tentativi ed errori)
  • Non si sta utilizzando una funzione di LINQ come IEnumerable<T>.Contains() che non funziona con CompiledQuery.
  • Hai già semplificato la query, che offre un maggiore vantaggio in termini di prestazioni, quando possibile.
  • Non si intende ulteriormente comporre i risultati della query (ad esempio, restringere o proiettare), che ha l'effetto di "decompilare" esso.

CompiledQuery fa il suo lavoro la prima volta che viene eseguita una query. Non dà alcun beneficio per la prima esecuzione. Come qualsiasi ottimizzazione delle prestazioni, in genere evita finché non sei sicuro di correggere un hotspot di prestazioni effettivo.

Aggiornamento 2012: EF 5 lo farà automaticamente (vedere "Entity Framework 5: Controlling automatic query compilation"). Quindi aggiungi "Non stai utilizzando EF 5" all'elenco precedente.

1

le query compilate sono più utili con le query linq con alberi di espressioni di grandi dimensioni che indicano query complesse per ottenere prestazioni su albero di espressioni di costruzione più e più volte durante il riutilizzo della query. nel tuo caso immagino che risparmierà pochissimo tempo.

+0

'SELECT ID, nome FROM Tags' vs' SELECT ID, nome FROM tag WHERE Nome LIKE '% nome% ''su una tabella di righe da 1M, la query compilata otterrà prestazioni eseguendo la prima selezione e quindi filtrerà i risultati sul codice? – BrunoLM

+0

per niente, dovresti filtrare i record a livello di DB non sul codice. errore di filtrare sul codice. query compilata significa solo che exp ression tree è pre compilato. la seconda query è la strada da percorrere –

0

Le query compilate offrono un miglioramento delle prestazioni, ma non è enorme. Se hai domande complesse, preferisco andare con una stored procedure o una vista, se possibile; lasciare che il database faccia la cosa potrebbe essere un approccio migliore.

+1

Bene, i nostri test mostrano che se si riutilizza la query può essere abbastanza veloce a causa del tempo di compilazione. Soprattutto se hai molte domande diverse. –

0

Le query compilate vengono compilate quando l'applicazione viene compilata e ogni volta che riutilizzi una query spesso o è complessa, devi assolutamente provare le query compilate per rendere l'esecuzione più veloce.

Ma non lo farei su tutte le query poiché è un po 'più di codice da scrivere e per query semplici potrebbe non valerne la pena.

Ma per ottenere il massimo delle prestazioni si dovrebbe anche valutare stored procedure in cui si fa tutta l'elaborazione sul server di database, anche se Linq cerca di spingere come gran parte del lavoro al db possibile si avrà situazioni in cui una stored procedure essere più veloce

+4

No, 'CompiledQuery' è compilato in fase di esecuzione, poco prima della prima esecuzione. –

6

Le query compilate consentono di risparmiare tempo, che sarebbe necessario per generare alberi di espressioni. Se la query viene usata spesso e salvi la query compilata, dovresti sicuramente usarla. Ho avuto molti casi in cui l'analisi delle query richiedeva più tempo del normale round trip nel database.

Nel tuo caso, se si è certi che avrebbe generato SELECT ID, Name FROM Tag senza il caso WHERE (cosa di cui dubito, come la funzione deve restituire AllQueriesIQueryable e la query effettiva deve essere effettuato solo dopo aver chiamato ToList) - non si deve usalo

Come qualcuno ha già detto, sui tavoli più grandi SELECT * FROM [someBigTable] ci vorrebbe molto tempo e passerai ancora più tempo a filtrare quello sul lato client. Quindi dovresti assicurarti che il tuo filtro sia fatto sul lato del database, non importa se stai usando query compilate o meno.