Come suggerisce il titolo, sto riscontrando un problema con la prima query su un database SQL Server utilizzando Entity Framework.Entity Framework - Prima query lenta
Ho provato a cercare una risposta su diversi siti ma nessuno sembra avere una soluzione.
Sto caricando un bel po 'di righe dal database incluse due relazioni 0-molti.
I test sono stati eseguiti in Visual Studio 2010 utilizzando il modello Entity Framework 4.0 e il generatore POCO (non c'è molta differenza nei tempi tra entità normali e oggetti POCO). Ho anche utilizzato il modello di viste T4 per precompilare le viste.
Il database era in SQL Server 2008.
Quello che vorrei davvero sapere è il motivo per cui la prima query è soo molto più lento rispetto a qualsiasi query secondarie.
Voglio anche sapere se è possibile fare qualcosa per aumentare la velocità della prima query fino al punto in cui è entro limiti accettabili.
Questa è una grande domanda e si può ottenere altre query che sono ancora più grande ed è comprensibile che essi possono essere un po 'lento, ma 30 secondi è troppo lento per l'utente di attendere, soprattutto quando gruppi di dati possono ottenere gli stessi dati molto più veloce.
Ho eseguito alcuni test di temporizzazione per cercare di scoprire dove si trova il problema e sono rimasto un po 'sorpreso nel vedere che sembra che SQL Server sia lento alla prima query.
Tempi è la seguente:
.NET Application Testing:
- prima query: 29,6 secondi
- seconda query: 3,2 secondi
SQL Profiler:
- First Qu ery: 27 secondi
- seconda query: 3,2 secondi
SQL Server Query Finestra
- prima query: 8 secondi
- seconda query: 4 secondi
Timings nell'applicazione è stata misurata con la classe Stopwatch
. È stata misurata solo la query e è stato utilizzato per eseguire la query.
I tempi in SQL Server Profiler si riferiscono alle stesse query eseguite nell'applicazione che mostrano che l'applicazione utilizza solo circa 2,6 secondi per riempire i dati negli oggetti.
Gli ultimi 27 secondi vengono utilizzati per l'esecuzione della query su SQL Server.
Guardando la query secondaria i tempi sono gli stessi sia per l'applicazione che per il server SQL ma l'esecuzione della query è molto più veloce questa volta.
Posso capire perché l'applicazione non utilizza in qualsiasi momento perché non ci sono nuove righe che devono essere convertite in oggetti, ma perché la query è molto più veloce, mi sarei aspettato qualche secondo a causa dei piani di esecuzione ma non 24 secondi.
Solo per scopi di test, ho copiato l'SQL che Entity Framework genera e ha aperto una nuova finestra di query con una connessione separata ed eseguito la query al suo interno.
Come puoi vedere occorrono 8 secondi per la prima query e 4 secondi per il secondo.
Spero che qualcuno abbia qualche suggerimento.
ps. Mi scuso per il muro di testo :)
Modifica 19-10-2010:
Ho eseguito ieri un test che sembra supportare le righe restituite in modo sequenziale. Ciò significa che quando una riga viene restituita dal database viene immediatamente materializzata (se non esiste già nel contesto), quindi viene restituita la riga successiva e così via.
Ecco perché sembra che la query impieghi molto tempo sul server di database perché il tempo di materializzazione è incluso nei tempi di profiler di SQL Server.
Non credo che questo sia un caso di lettura di SQL Server dal disco rigido. La query lenta si verifica ogni volta che c'è una "prima query" in EF.
ex.
- Eseguire la prima query con EF, l'istruzione SQL è più lenta allora qualsiasi richiesta secondaria
- Smaltire contesto/repository
- Creare un nuovo contesto
- Eseguire la stessa query come prima (di nuovo la prima la query è lenta e quindi l'istruzione SQL)
È quasi come se l'EF invia alcune opzioni insieme alla prima query che rallenta il server.
Come per la compilazione di query, poiché ricordo che la query è stata compilata la prima volta che viene utilizzata il che significa che la prima query richiederebbe ancora più tempo per l'esecuzione.
Le query secondarie sarebbero più veloci ma la velocità sulle query secondarie non è il problema.
Ho eseguito anche un test in cui ho creato una query compilata come statica in modo che fosse compilata per tutti i contesti creati.
Ho quindi creato un contesto, ho eseguito la query, distrutto il contesto e ne ho creato uno nuovo ed ho eseguito la stessa query ancora una volta.
La differenza non era così grande, solo pochi secondi e la prima volta che ho eseguito la query ci sono voluti ancora tanto tempo senza pre-compilarlo.
Come per la generazione di viste, lo implementiamo già utilizzando i modelli T4.
La risposta è davvero che EF funziona solo se non si fa nulla se non le query più semplici che restituiscono solo una quantità relativamente piccola di dati?
Ci scusiamo per la risposta in ritardo. Non credo che questo sia un caso di lettura del server SQL dal disco fisso. La query lenta si verifica ogni volta che esiste una "prima query" in EF. Per esempio. 1) Esegui la prima query con EF, l'istruzione SQL è più lenta di qualsiasi query secondaria. 2) Disponi il contesto/repository. 3) Crea un nuovo contesto. 4) Esegui la stessa query di prima. (di nuovo la prima query è lenta e quindi l'istruzione SQL) È quasi come se l'EF invia alcune opzioni insieme alla prima query che rallenta il server. –
Per quanto riguarda la compilazione delle query, credo che la query sia compilata la prima volta che viene utilizzata, ad esempio la prima query richiederebbe ancora più tempo per essere eseguita. Le query secondarie sarebbero più veloci ma la velocità sulle query secondarie non è il problema. Ho anche fatto un test in cui ho creato una query compilata statica in modo che fosse compilata per tutti i contesti che sono stati creati. Ho quindi creato un contesto, ho eseguito la query, ho eliminato il contesto, ne ho creato uno nuovo e ho eseguito nuovamente la query. La differenza non era così grande, solo pochi secondi, e la prima volta che ho eseguito la query ci sono voluti ancora tanto tempo senza doverla precompilare. –
Come per Generazione vista, lo implementiamo già utilizzando i modelli T4. La risposta è davvero che EF funziona solo se non fai altro che le query più semplici che restituiscono solo una quantità relativamente piccola di dati? –