2014-06-23 17 views
7

I codice un'applicazione lato server con java eseguito su server linux. Uso la sospensione per aprire la sessione nel database, utilizzare sql nativo per interrogarlo e chiudere sempre questa sessione provando, catturando, infine.Utilizzo memoria elevato durante l'utilizzo di Hibernate

Il mio DB di query del server che utilizza la modalità Hibernate con frequenza molto alta.

Ho già definito MaxHeapSize perché è 3000M ma solitamente utilizza 2.7 GB su RAM, può diminuire ma più lentamente di aumentare. A volte cresce fino a 3,6 GB di memoria, più del mio MaxHeapSize definito all'avvio.

Quando la memoria utilizzata è 3,6 GB, provo a scaricarlo con il comando -jmap e ho ottenuto un heapdump con dimensioni solo di 1,3 GB.

Im usando MAT Eclipse per analizzarlo, ecco l'albero Dominator da MAT Dominator tree Credo che Hibernate è il problema, ho tanti org.apache.commons.collections.map.AbstractReferenceMap $ ReferenceEntry come questo. Forse non può essere smaltito dalla raccolta dei rifiuti o può ma lento.

Come posso risolvere il problema?

risposta

10

Hai 250k voci nell'elenco di query IN. Anche una query nativa mette il database in ginocchio. Oracle limita l'elenco delle query IN a 1000 per motivi di prestazioni, quindi è necessario fare lo stesso.

Dargli più RAM non risolverà il problema, è necessario limitare la selezione/gli aggiornamenti a un massimo di 1000 voci, utilizzando la paginazione.

Streaming is an option, ma, per un set di risultati così ampio, keyset pagination è in genere l'opzione migliore.

Se è possibile eseguire tutta l'elaborazione nel database, non sarà necessario spostare 250k record dal DB all'app. C'è una buona ragione per cui molti RDBMS offrono linguaggi procedurali avanzati (ad esempio PL/SQL, T-SQL).

+0

Puoi insegnarmi un po 'di più? Ho poca esperienza sull'interazione del database Oracle. – Viet

+1

È necessario recuperare N voci, aggiornarle quindi recuperare il batch successivo e così via. –

+0

sono ancora confuso, nella mia domanda "AGGIORNAMENTO .. ​​DOVE .. IN (...) ", L'elenco delle query IN è piccolo e non può raggiungere 1000. E quando si espande in foglia dell'albero Dominator in MAT eclissi, trovo la mia query di selezione ('sqlQueryCheckSet' nel mio codice), molti di esso, e penso solo it – Viet

1

Graziecon il tuo collegamento a Hibernate issue, questo è un bug su ibernazione, risolve sulla versione 3.6. Ho appena aggiornato la mia versione ibidata 3.3.2 alla versione 3.6.10, uso il valore predefinito di "hibernate.query.plan_cache_max_soft_references" (2048), "hibernate.query.plan_cache_max_strong_references" (128) e il mio problema è scomparso. Niente più alti consumi di memoria.

3

Si noti che anche se il numero di oggetti all'interno della queryPlanCache può essere configurato e limitato, probabilmente non è normale avere così tanto.

Nel nostro caso abbiamo scritto query in HQL simile a questo:

hql = String.format("from Entity where msisdn='%s'", msisdn); 

Ciò ha provocato N diverse query che vanno al queryPlanCache. Quando abbiamo cambiato la query:

hql = "from Blacklist where msisnd = :msisdn"; 
... 
query.setParameter("msisdn", msisdn); 

la dimensione di queryPlanCache stato drasticamente ridotto da 100Mb a quasi 0. Questa seconda query viene tradotto in un un'unica preparedStament risultante solo oggetto all'interno della cache.