.net Qual è il modo migliore per migliorare le prestazioni di NHibernate?




performance orm (10)

Ho un'applicazione che utilizza NHibernate come ORM e talvolta presenta problemi di prestazioni a causa del modo in cui i dati sono accessibili da esso. Che tipo di cose si possono fare per migliorare le prestazioni di NHibernate? (Si prega di limitare a una raccomandazione per risposta)


Answer #1

NHibernate genera SQL abbastanza veloce, appena estratto dalla scatola. Lo sto usando da un anno e non ho ancora dovuto scrivere nuda SQL con esso. Tutti i miei problemi di prestazioni sono stati dalla normalizzazione e dalla mancanza di indici.

La soluzione più semplice è esaminare i piani di esecuzione delle query e creare indici appropriati, in particolare sulle colonne delle chiavi esterne. Se si utilizza Microsoft SQL Server, "Ottimizzazione guidata motore di database" è di grande aiuto.


Answer #2

Nessuna raccomandazione ma uno strumento per aiutarti: NH Prof ( http://nhprof.com/ ) sembra essere promettente, può valutare il tuo utilizzo del framework ORM. Può essere un buon punto di partenza per il tunning di NHibernate.


Answer #3

Senza particolari sui tipi di problemi di prestazioni che stai vedendo, posso solo offrire una generalizzazione: nella mia esperienza, la maggior parte dei problemi di prestazioni delle query del database derivano dalla mancanza di indici appropriati. Quindi il mio suggerimento per una prima azione sarebbe quello di controllare i piani di query per le query non indicizzate.


Answer #4

Evita e / o minimizza il problema Seleziona N + 1 riconoscendo quando passare dal caricamento lento a quello avido per le query a bassa esecuzione.


Answer #5

Memorizzazione nella cache, memorizzazione nella cache, memorizzazione nella cache: si sta utilizzando il caching di primo livello correttamente [chiudendo le sessioni prematuramente o utilizzando StatelessSession per ignorare la memorizzazione nella cache di primo livello]? È necessario impostare una cache di secondo livello semplice per valori che cambiano raramente? È possibile memorizzare nella cache i set di risultati della query per accelerare le query che cambiano raramente?

[Anche configurazione: puoi impostare gli elementi come immutabili? Riesci a ristrutturare le query per riportare solo le informazioni necessarie e trasformarle nell'entità originale? Batman riuscirà a fermare l'Enigmista prima che arrivi alla diga? ... oh, scusa mi sono portato via.]


Answer #6

Quello che ha detto un sacco di tempo libero.

Leggi il capitolo 19 della documentazione, "Miglioramento delle prestazioni".
NHibernate: http://nhibernate.info/doc/nhibernate-reference/performance.html
Hibernate: http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html

Utilizzare SQL Profiler (o equivalente per il database che si sta utilizzando) per individuare query di lunga durata. Ottimizza quelle query con indici appropriati.

Per le chiamate al database utilizzate su quasi ogni singola pagina di un'applicazione, utilizzare CreateMultiQuery per restituire più set di risultati da una singola query del database.

E, naturalmente, cache. La direttiva OutputCache per pagine / controlli. Memorizzazione nella cache di NHibernate per i dati.


Answer #7

Posso solo limitare la mia risposta a un'opzione? In tal caso, selezionarei di implementare il meccanismo di cache di secondo livello di NHibernate.

In questo modo, per ogni oggetto nel tuo file di mappatura puoi definire la strategia della cache. La cache di secondo livello manterrà gli oggetti già recuperati in memoria e quindi non effettuerà un altro roundtrip al database. Questo è un enorme richiamo alle prestazioni.

Il tuo obiettivo è definire gli oggetti che sono costantemente accessibili dalla tua applicazione. Tra quelli ci saranno impostazioni generali e simili.

C'è un sacco di informazioni da trovare per la cache di secondo livello e la sua implementazione.

In bocca al lupo :)


Answer #8

"Solo una raccomandazione per risposta"? Quindi vorrei andare per questo:

Evitare di unire duplicati (prodotti cartesiani AKA) a causa di join lungo due o più associazioni parallele a molte; utilizzare invece sotto-sottoquery, MultiQueries o FetchMode "subselect".

Tratto da: Hibernate Performance Tuning Tips


Answer #9

Il primo e più drammatico problema di prestazioni che puoi incontrare con NHibernate è se stai creando una nuova factory di sessione per ogni sessione che crei. Dovrebbe essere creata solo un'istanza di produzione di sessione per ogni esecuzione di applicazione e tutte le sessioni dovrebbero essere create da quella fabbrica.

Lungo queste linee, dovresti continuare a utilizzare la stessa sessione finché ha senso. Questo può variare a seconda dell'applicazione, ma per la maggior parte delle applicazioni Web è consigliata una singola sessione per richiesta. Se passi via frequentemente la tua sessione, non stai ottenendo i benefici della sua cache. L'uso intelligente della cache di sessione può modificare una routine con un numero di query lineare (o peggiore) a un numero costante senza molto lavoro.

Altrettanto importante è che si desidera assicurarsi di essere pigri a caricare i riferimenti dell'oggetto. Se non lo sei, interi grafici di oggetti potrebbero essere caricati anche per le query più semplici. Ci sono solo alcuni motivi per non farlo, ma è sempre meglio iniziare con il caricamento lazy e tornare quando necessario.

Questo ci porta a prendere con entusiasmo, l'opposto del caricamento pigro. Mentre attraversi le gerarchie degli oggetti o esegui il looping delle raccolte, può essere facile perdere traccia del numero di query che stai creando e ti ritroverai con un numero esponenziale di query. Il recupero di Eager può essere fatto su una base per query con un FETCH JOIN. In rari casi, ad esempio se è presente una determinata coppia di tabelle che si recupera sempre, prendere in considerazione la disattivazione del caricamento lento per tale relazione.

Come sempre, SQL Profiler è un ottimo modo per trovare le query che stanno rallentando o che vengono eseguite ripetutamente. Al mio ultimo lavoro avevamo una funzione di sviluppo che contava anche le richieste per pagina. Un numero elevato di query per una routine è l'indicatore più ovvio che la tua routine non funziona bene con NHibernate. Se il numero di query per routine o richiesta sembra buono, probabilmente si sta procedendo con il tuning del database; assicurandoti di avere abbastanza memoria per archiviare piani di esecuzione e dati nella cache, indicizzare correttamente i tuoi dati, ecc.

Uno dei piccoli problemi che abbiamo incontrato è stato con SetParameterList (). La funzione consente di passare facilmente un elenco di parametri a una query. NHibernate lo ha implementato creando un parametro per ogni elemento passato. Ciò comporta un piano di query diverso per ogni numero di parametri. I nostri piani di esecuzione venivano quasi sempre rilasciati dalla cache. Inoltre, numerosi parametri possono rallentare in modo significativo una query. Abbiamo eseguito una modifica personalizzata di NHibernate per inviare gli elementi come un elenco delimitato in un singolo parametro. L'elenco è stato separato in SQL Server da una funzione del valore di tabella che il nostro hack è stato inserito automaticamente nella clausola IN della query. Potrebbero esserci altre mine terrestri come questa a seconda dell'applicazione. SQL Profiler è il modo migliore per trovarli.


Answer #10

Se non stai già utilizzando il caricamento lazy (appropriatamente), avvia. Recuperare le raccolte quando non ne hai bisogno è uno spreco di tutto.

Il capitolo Miglioramento delle prestazioni descrive questo e altri modi per migliorare le prestazioni.







data-access-layer