Ich habe seit mehreren Tagen mit einer Abfrage auf Hibernate gegen eine Oracle-Datenbank gekämpft. So etwas wird zum Einspeisen von Datensätzen in ein Raster verwendet.Hibernate parametrisierte SQL-Abfrage langsam und aktiv Oracle-Sitzungen
SELECT
fields
FROM
tables and JoinedTables
WHERE
Field1 >= :value1
AND Field2 = :value2
AND Field3 = :value3
Order By MaintTable.Id Desc
Verwendung dieses Ansatzes in einer Spring Java + Hibernate 4.2-Methode.
Jedes gefilterte Feld ist korrekt indiziert und erstellt einen Funktionsindex auf Maintable.Id Descendent, um die Leistung zu verbessern.
Zuerst dachte ich, es war, Session/Connection-Pool nicht richtig verwaltet werden, damit ich geändert StatelessSession und fügen Sie diese 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;
Es es nicht gelöst hat. Abfrage läuft ein paar Mal in Ordnung, aber aus einem unbekannten Grund, und die Verwendung von Werten, die bereits zuvor mit Erfolg ausgeführt wurden, hängt, Sitzung in Oracle (Status = ACTIVE) geöffnet und schlägt bei Timeout fehl. Die gleiche Abfrage, die auf jedem SQL-Client gegen Oracle ausgeführt wird und Dutzende von Malen mit allen möglichen Kombinationen von Parametern mit extremer Leistung, etwa 400 ms, für 10 Datensätze gleichzeitig ausgeführt wird.
Nach einigen Artikeln hier und da zu lesen, Link1 [Slow performance on Hibernate + Java but fast when I use TOAD with the same native Oracle query Link2: [query hangs oracle 10g
ich schlecht Auswertungsplan supected von Hibernate verwendet wurde, und beschlossen, alle Filter mit gebundenen Parametern zu entfernen und auch nicht gelöst haben, obwohl es ein bisschen besser war. Nach einer Weile hängen, wenn auf andere Seiten wie Page 1, 2,3,4 bewegen, ...
Nach alldem, vermutete ich, der durch Hibernate Methoden generiert SQL
query.setMaxResults(rows)
query.setFirstResult(SomeHelperMethod(page, rows));
Da Säge in Protokoll, dass sie wurden als Bindeparameter an Oracle übergeben.
...
Order By Certificado.Id Desc) row_
where rownum <= ?)
where rownum_ > ?
Ich sah auch dies im Trace-Log
2015-09-15 14:09:53 TRACE QueryPlanCache:200 - Located native-sql query plan in cache (SELECT /*+ INDEX(
und diese:
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
Schließlich hatte ich alle Hibernate binden params zu verlassen und implementiert individuelle Berechnung Paginierung und schrieb alle SQL um die Seitenzeilen abzurufen und um db-Sitzungen korrekt auszuführen und zu verwalten.
Also, meine Frage ist: Was die Szenen Behing Ist Ruhezustand zu tun, dass die Abfrage auszuführen verhindert, da es gegen die Datenbank ausgeführt wird? Gibt es ein bekanntes Problem mit Bind Parameter-Abfragen?
Ich mag es nicht wirklich, den ganzen SQL-Code zu schreiben und zwingt hart-Parsing dieses SQL, wenn ich Bindungsparameter habe.
Einige Anmerkungen zur Umgebung: Tomcat und Oracle sind auf demselben Host.So Netzwerkverbindung ist nicht das Problem
Hibernate Version 4.2.15 final
Der Tisch hat rund 300k recs in dev-Datenbank (1,5M auf Production) und zeigt Seiten von 10, 20, 50 recs zu einer Zeit, , sortiert nach Primärschlüssel Beschreibung (Sequence generated)
Ich hoffe, einige Hibernate-Experten können mir dabei helfen, sodass ich Hibernate-Abfragen bei großen Datenbankprojekten immer noch vertrauen kann. Vielen Dank im Voraus.
Haben das gleiche Problem. In MySQL Workbench dauert die Abfrage 0 ms. In Hibernate dauert es 1500ms. –
Nehmen Sie alle Hibernate-Parameter heraus und erstellen Sie die SQL-Abfrage selbst mit allen in der SQL-Zeichenfolge festgelegten Parametern. Es funktionierte für mich. Genau wie es eine JDBC Old School-Abfrage war. –
Danke für den Tipp. Auf jeden Fall einen Versuch wert! –