2013-05-06 4 views
5

Ho una pagina di accesso che esegue una query EF molto semplice per determinare se un utente è valido. Alla prima esecuzione questa query impiega circa 6 secondi per essere eseguita. Nelle corse successive ci vuole molto meno di un secondo.Come inizializzare le query di Entity Framework per velocizzarle?

Ho esaminato un articolo che parlava dell'utilizzo di Application Auto-Start e la mia domanda è questa: esiste un modo per attivare questa query per causare qualsiasi occorrenza della memorizzazione nella cache senza effettivamente chiamare la query oppure è necessario per me basta chiamare la query con una serie fittizia di argomenti?

MODIFICA: Quando dico sei secondi, mi riferisco al tempo necessario per ottenere la query. Codice simile a questa (nota in questo caso è un contactID int nullable e impostare a null):

return from contact in _context.Contacts 
      where contact.District == Environment.District && 
      contact.ContactId == (contactID ?? contact.ContactId) 
      select contact; 

Questa è una SqlServer 2008 e ho eseguito un profiler per controllare il codice SQL e la durata restituisce è 41 ms per la query che alla fine viene eseguita. Il ritardo di 6 o 7 secondi si verifica prima che la query raggiunga anche SQL. Sto provando a impostare ora un'occhiata per vedere se può darmi ulteriori dettagli su altre cose che potrebbero accadere nello stesso momento.

+0

Penso che valga la pena di fare un po 'di profilazione e tentare di scoprire dove si sta effettivamente verificando il ritardo. –

+0

l'overhead di EF è piuttosto leggero e probabilmente non è il problema. Forse installare qualcosa come Glimpse (pacchetto NuGet) e vedere cosa è davvero la colpa.Potresti avere altri eventi che sono davvero in colpa (componenti aggiuntivi bootstrap?). –

+0

@RobertHarvey Intendi il profiling SQL o il profiling .NET? – Mykroft

risposta

2

Questo suona davvero come si chiama una "query fredda". Il collo di bottiglia delle prestazioni principali per le query a freddo è "Visualizza generazione" che viene eseguito una volta per AppDomain dell'applicazione. In genere, l'effetto è che la prima query - e non importa quale - è lenta e le query successive sono veloci.

Non deve necessariamente essere una query che potrebbe essere lenta. Se la prima operazione che fai con EF nella tua applicazione è un inserimento che sarebbe lento. O anche un Attach che non tocchi affatto il database sarebbe lento. A proposito: aggiungere un context.Users.Attach(new User()) all'avvio dell'applicazione e guardare nel debugger quanto tempo ci vuole per passare quella linea.)

In tutti i casi il tempo viene consumato costruendo una struttura di dati interna in memoria - la query locale "viste" (non hanno nulla a che fare con le viste della tabella del database) - che si svolge una volta per AppDomain.

La Generazione vista è descritta con here in dettaglio e here dove è anche possibile trovare le risorse su come "pre-generare" tali viste come parte del processo di generazione e prima della distribuzione. (Nota: è necessario aggiornare questi pre-generati ogni volta che si modifica il modello e ridistribuire l'applicazione.)

Il modo alternativo è di attivare il caricamento periodico dell'applicazione Web avviando (con un processo ad esempio che raggiunge il sito) . In applicazione si avvia eseguire qualsiasi richiesta fittizio o la cosa Attach sopra o chiamare l'inizializzazione EF manualmente:

using (var context = new MyContext()) 
{ 
    context.Database.Initialize(false); 
} 

Modifica

ho dimenticato l'ultima soluzione. Ignora solo i 6 o 7 secondi. Se il tuo sito diventa famoso e ha un traffico ragionevole, è improbabile che una query così fredda si verifichi perché il processo di lavoro IIS interromperà raramente l'AppDomain. L'utente occasionale che colpisce il sito durante la notte quando una chiusura di questo tipo si è verificata poco prima è probabilmente troppo stanco per notare persino il ritardo.

+1

Questa è la codifica aziendale, quindi "diventare famosi" non funziona come soluzione :). Ma penso che la chiamata Initialize combinata con l'auto-start dell'applicazione possa risolvere il mio problema. Lo metterò alla prova oggi. Grazie. – Mykroft

+0

"troppo stanco per notare persino il ritardo." - a meno che non siano in un fuso orario diverso. – mayu