2013-01-12 10 views
11

Ho rilevato un problema di prestazioni con le query hibernate e native su Oracle. Quando eseguo una query SQL complessa con diversi parametri su TOAD, ottengo il risultato in millisecondi. Tuttavia, quando eseguo la stessa query utilizzando Hibernate questa volta viene incrementato enormemente (fino a quattro secondi o anche più).Prestazioni lente su Hibernate + Java ma veloce quando utilizzo TOAD con la stessa query Oracle nativa

La mia query SQL è piuttosto complessa, restituisce un valore univoco (quindi, il problema non è correlato con il tempo necessario alle classi di installazione) e contiene diversi parametri con il formato ': nameParameter'. Questa query è archiviata in una stringa. Ad esempio,

String myNamedNativeQuery = "select count(*) from tables "+ 
          "where column1 = :nameParameter1 "+ 
          "and column2 = :nameParameter2"; 
          //actually my sentence is much more complex!! 

Quando si esegue la frase su TOAD, viene risolto in pochi millisecondi. Ma usando questa frase con Hibernate

SQLQuery query = session.createSQLQuery("myNamedNativeQuery"); 

query.setParameter(nameParameter1, value1); 
query.setParameter(nameParameter2, value2); 

query.uniqueResult(); 

sono necessari diversi secondi per ottenere lo stesso risultato.

Mi sono reso conto che se ho sostituito i parametri direttamente sulla query nativa e poi eseguo la frase utilizzando Hibernate il tempo diminuisce drasticamente. Sarebbe qualcosa del genere:

String strQuery = session.getNamedQuery("myNamedNativeQuery").getQueryString(); 

myNamedNativeQuery = myNamedNativeQuery.replace("nameParameter1", value1); 
myNamedNativeQuery = myNamedNativeQuery.replace("nameParameter2", value2); 

SQLQuery query = session.createSQLQuery("myNamedNativeQuery"); 
query.uniqueResult(); 

Qualcuno sa cosa sta succedendo ??

Grazie in anticipo.

PS: La versione di Oracle è 9i e Hibernate 3.2

+1

turno dell'opzione "mostra sql" con ibernazione. Ti mostrerà la query di ibernazione in corso e ti fornirà informazioni sul motivo per cui è necessario così tanto tempo. –

risposta

6

Penso che quello che sta succedendo con questo codice:

SQLQuery query = session.createSQLQuery("myNamedNativeQuery"); 
query.setParameter(nameParameter1, value1); 
query.setParameter(nameParameter2, value2); 
query.uniqueResult(); 

è questo: based è creato un piano di query:

alla linea 1 su alcuni valori previsti per i parametri specificati.

alla riga 4: la query viene eseguita con valore1 e valore2, ma quei valori non sono "buoni valori" per il piano di query elaborato alla riga 1 e quindi, il database sta eseguendo un piano molto inappropriato per l'effettivo valori e ci vuole un sacco di tempo.

Perché?

Guardando il codice sorgente di HibernateSessionImpl.createSQLQuery(...) ho trovato questa riga di codice:

SQLQueryImpl query = new SQLQueryImpl(
       sql, 
         this, 
         factory.getQueryPlanCache().getSQLParameterMetadata(sql) 
     ); 

che sta chiamando getQueryPlanCache() con qualche parameterMetaData. Suppongo che questo metadata non sia abbastanza buono.

+0

Interessante ... Quindi, quale sarebbe la migliore pratica in questi casi ?? Forse sostituire i parametri con i loro valori prima di chiamare createSQLQuery()? – Sobrino

+0

Forse la condivisione adattiva del cursore potrebbe essere d'aiuto. Ma quella funzione non è disponibile fino a 11g. –

+0

Secondo i miei test, questa situazione si verifica utilizzando anche session.getNamedQuery ('myNamedQuery'). Sembra che Hibernate stia memorizzando nella cache i piani di query e con alcuni parametri il piano di query scelto non è il migliore. Quindi, sarebbe possibile configurare la cache del piano di query? – Sobrino

0

La mia risposta a voi è:

Rimuovere tutti i parametri legano e utilizzare StatelessSession invece di sessione

Uso SQLQuery invece di query con piena SQL tra cui parametro valori

StatelessSession session = sessionFactory.openStatelessSession(); 

ho avuto problema simile e fino a quando non avrò trovato una soluzione migliore, sono riuscito a farlo funzionare. Vedere Hibernate parameterized sql query slow and active oracle sessions

Problemi correlati