Ho sofferto per diversi giorni con una query su ibernazione contro un database Oracle. Qualcosa di simile è usato per alimentare i record in una griglia.Hibernate con query sql con parametri lenta e sessioni oracle attive
SELECT
fields
FROM
tables and JoinedTables
WHERE
Field1 >= :value1
AND Field2 = :value2
AND Field3 = :value3
Order By MaintTable.Id Desc
Utilizzo di questo approccio in un metodo Spring Java + Hibernate 4.2.
Ogni campo filtrato viene indicizzato correttamente e creato un indice di funzione su Maintable.Id Discendente per migliorare le prestazioni.
In un primo momento ho pensato che fosse pool di sessione/connessione non viene gestito correttamente, così ho cambiato per StatelessSession e aggiungi a Session.close():
query.setCacheable(false)
.setTimeout(30)
.setReadOnly(true);
...
...
//Pagination
query.setMaxResults(rows);
query.setFirstResult(HelperMethod(page, rows));
result = (List<CertificateViewEnt>) query.list();
session.close();
return result;
Non ha risolto. Query esegue un paio di volte ok, ma per qualche motivo sconosciuto e utilizzando valori che erano già stati eseguiti in precedenza con successo, si blocca, lascia la sessione aperta in Oracle (stato = ATTIVO) e fallisce il timeout. La stessa query eseguita su Oracle su qualsiasi client SQL e decine di volte con tutte le possibili combinazioni di parametri viene eseguita con prestazioni estreme, circa 400ms, per 10 record alla volta.
Dopo aver letto alcuni articoli qua e là, Link1 [Slow performance on Hibernate + Java but fast when I use TOAD with the same native Oracle query Link2: [query hangs oracle 10g
I supected di QueryPlan mal utilizzato da Hibernate e ha deciso di rimuovere tutti i filtri che utilizzano i parametri legati e inoltre, non ha risolto, anche se era un po 'meglio. Dopo un po 'impiccato quando si spostano in altre pagine come pagina 1, 2,3,4, ...
Dopo tutto questo, ho sospettato di SQL generato da metodi di Hibernate
query.setMaxResults(rows)
query.setFirstResult(SomeHelperMethod(page, rows));
Perché sega a registro che venivano passati come parametri di collegamento a Oracle.
...
Order By Certificado.Id Desc) row_
where rownum <= ?)
where rownum_ > ?
ho visto anche questo nel Registro di traccia
2015-09-15 14:09:53 TRACE QueryPlanCache:200 - Located native-sql query plan in cache (SELECT /*+ INDEX(
e questo:
2015-09-15 14:09:53 TRACE BasicBinder:84 - binding parameter [2] as [VARCHAR] - E
2015-09-15 14:09:53 DEBUG Loader:2031 - bindNamedParameters() 0 -> deleted [3]
2015-09-15 14:09:53 TRACE BasicBinder:84 - binding parameter [3] as [INTEGER] - 0
2015-09-15 14:09:53 TRACE Loader:1931 - Bound [7] parameters total
/*
SLOW here !!! Around 3 secs when query runs in ~0,300 secs via SQL client.
And ACTIVE sessions are left running in Oracle.
*/
2015-09-15 14:09:56 TRACE JdbcCoordinatorImpl:397 - Registering result set [[email protected]]
2015-09-15 14:09:56 TRACE Loader:943 - Processing result set
Alla fine ho dovuto abbandonare tutti i params legano Hibernate e attuate impaginazione calcolo personalizzato e scritto tutto SQL per recuperare le righe della pagina e sta funzionando e gestendo correttamente le sessioni db.
Quindi, la mia domanda è: Che cosa è letargo facendo behing le scene che impedisce la query da eseguire durante l'esecuzione sul database? C'è qualche problema noto con le query sui parametri di bind?
Non mi piace scrivere tutto il codice SQL e forzare l'analisi di questo SQL, quando ho dei parametri di bind.
Alcune note sull'ambiente: Tomcat e Oracle si trovano sullo stesso host.Quindi connessione di rete non è il problema
versione 4.2.15 Hibernate finale
La tabella ha circa 300k RECS nel database dev (1,5m sulla produzione) e mostra le pagine di 10, 20, 50 RECS alla volta , ordinati per chiave primaria Desc (sequenza generata)
Spero che alcuni esperti di Hibernate possano aiutarmi in questo modo, così posso ancora fidarmi delle query di Hibernate su progetti di database di grandi dimensioni. Grazie in anticipo.
Avendo lo stesso problema. In MySQL Workbench la query impiega 0 ms. In Hibernate ci vogliono 1500ms. –
Elimina tutti i parametri di Hibernate e crea la query SQL tutto da solo con tutti i parametri impostati nella stringa SQL. Ha funzionato per me. Proprio come se fosse una query della vecchia scuola JDBC. –
Grazie per il suggerimento. Sicuramente vale la pena provare! –