2015-09-15 19 views
7

Od kilku dni borykam się z zapytaniem o hibernację przeciwko bazie danych Oracle. Coś podobnego do tego, które służy do podawania rekordów do siatki.Hibernate sparametryzowane zapytanie sql wolne i aktywne sesje oracle

SELECT 
    fields 
FROM 
    tables and JoinedTables 
WHERE 
     Field1 >= :value1 
    AND Field2 = :value2 
    AND Field3 = :value3 
Order By MaintTable.Id Desc 

Stosowanie tego podejścia w wiosennej wersji Java + Hibernacja 4.2.

SQLQuery query = (SQLQuery) session.createSQLQuery(querySql) 
           .addEntity(CertificateViewEnt.class) 
           .setParameter("value1", firstCertificateRecordDate) 
           .setParameter("value2", certType.toUpperCase()) 
           .setParameter("value3", deleted? 1:0);  

Każde przefiltrowane pole jest poprawnie indeksowane i tworzy indeks funkcji na Maintable.Id Descendent, aby poprawić wydajność.

Na początku myślałem, że to basen sesji/połączenia nie są prawidłowo zarządzane, więc zmieniłem na StatelessSession i dodaj 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; 

To nie rozwiązany. Kwerenda działa kilka razy OK, ale z jakiegoś nieznanego powodu i przy użyciu wartości, które zostały wcześniej uruchomione z sukcesem, zawiesza się, pozostawia sesję otwartą w Oracle (status = AKTYWNY) i kończy się niepowodzeniem po przekroczeniu limitu czasu. To samo zapytanie jest uruchamiane przeciwko Oracle na dowolnym kliencie SQL i dziesiątki razy z wszystkimi możliwymi kombinacjami wykonywanych paramerów z ekstremalną wydajnością, około 400ms, dla 10 rekordów naraz.

Po przeczytaniu kilka artykułów tutaj i tam, 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 słabo QueryPlan używany przez Hibernate i postanowił usunąć wszystkie filtry wykorzystaniem parametrów związanych i również nie rozwiązany, choć było trochę lepiej. Po chwili powiesił po przeniesieniu do innych stron jak strona 1, 2,3,4, ...

Po tym wszystkim, że ja podejrzany o SQL generowany przez metody hibernacji za

query.setMaxResults(rows) 
query.setFirstResult(SomeHelperMethod(page, rows)); 

Ponieważ piła w dzienniku, że zostały przekazane jako parametry wiązania do Oracle.

 ... 
     Order By Certificado.Id Desc) row_ 
     where rownum <= ?) 
    where rownum_ > ? 

Widziałem też ten w ślad Log

2015-09-15 14:09:53 TRACE QueryPlanCache:200 - Located native-sql query plan in cache (SELECT /*+ INDEX(

a to:

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 

końcu musiałem porzucić wszystkie wiążą params Hibernate i wdrożone obliczeń zwyczaj paginacji i napisał wszystkie SQL aby pobrać wiersze strony i poprawnie obsługuje sesje db.

Tak, moje pytanie brzmi: Co to jest hibernacja robiąca sceny, które uniemożliwiają uruchomienie zapytania w wyniku działania bazy danych? Czy jest jakiś znany problem z zapytaniami o parametry powiązania?

Naprawdę nie lubię pisać całego kodu SQL i wymuszać ciężkie parsowanie tego SQL, gdy mam parametry wiązania.

Kilka uwag na temat środowiska: Tomcat i Oracle znajdują się na tym samym hoście.Więc połączenie sieciowe nie jest problemem

wersja 4.2.15 Hibernate końcowy

tabela ma około 300k regionalnych wspólnot gospodarczych w bazie dev (1,5m na produkcji) i pokazuje strony 10, 20, 50 REC naraz , posortowane według klucza głównego Desc (wygenerowana sekwencja)

Mam nadzieję, że niektórzy eksperci Hibernate mogą mi pomóc w tym zakresie, aby nadal móc ufać zapytaniom Hibernate w dużych projektach bazodanowych. Z góry dzięki.

+0

Mając ten sam problem. W środowisku MySQL Workbench zapytanie trwa 0 ms. W stanie hibernacji trwa to 1500ms. –

+0

Usuń wszystkie parametry Hibernate i samodzielnie zbuduj zapytanie SQL ze wszystkimi parametrami ustawionymi w ciągu SQL. To zadziałało dla mnie. Tak jak to było w przypadku starej szkoły JDBC. –

+0

Dzięki za cynk. Zdecydowanie warto spróbować! –

Odpowiedz

1

Nie wiem, czy to jest twój problem, ale Oracle szuka wartości zmiennych podczas analizowania zapytania, a następnie zapisuje plan zapytania dla przyszłych wykonań, więc nie musi dalej analizować zapytania za każdym razem, gdy jest uruchom z nowym zestawem zmiennych wiązania. Ale co jakiś czas zapytanie jest ponownie analizowane. Jeśli zdarzy się, że jakieś nietypowe wartości wiążące zostaną przekazane podczas analizowania, wówczas niepoprawny plan zostanie zapisany i użyty. Jest to rodzaj przekleństwa zmiennych wiązania. Zmniejszają przetwarzanie, ale mogą odwrócić plan na nietypowych wartościach zmiennych wiązania, gdy zapytania są ponownie analizowane. Wskazówki mogą pomóc. Używamy profili SQL do blokowania planów zapytań za pomocą zmiennych wiążących, które mają tendencję do zmiany planów. Czasami można dostosować czas i sposób gromadzenia statystyk optymalizatora, aby utworzyć dobry plan niezależnie od wartości przekazywanych do zmiennych wiążących.

W każdym razie jest to coś, co widzę przez cały czas i może, ale nie musi, być twoim problemem.

Bobby