2014-06-23 13 views
7

Koduje aplikację po stronie serwera z uruchomionym java na serwerze Linux. Używam hibernacji do otwierania sesji do bazy danych, używam natywnego sql do wysyłania zapytań i zawsze zamykam tę sesję, spróbuj, złap, wreszcie.Wysoki poziom wykorzystania pamięci podczas korzystania z Hibernate

Zapytanie DB o mój serwer za pomocą hibernacji o bardzo wysokiej częstotliwości.

Już definiuję MaxHeapSize, ponieważ jest to 3000M, ale zwykle korzysta z 2.7 GB pamięci RAM, może się zmniejszyć, ale wolniej niż wzrost. Kiedyś wzrasta zużycie pamięci do 3,6 GB, więcej niż mój MaxHeapSize określić przy starcie.

Gdy używana pamięć to 3,6 GB, próbuję ją zrzucić poleceniem -jmap i otrzymałem stertę o rozmiarze 1,3 GB.

Im przy użyciu Eclipse MAT aby je analizować, oto drzewo dominator od MAT Dominator tree myślę hibernacji jest problem, mam tak wiele org.apache.commons.collections.map.AbstractReferenceMap $ ReferenceEntry tak. Być może nie można go pozbyć się poprzez zbieranie śmieci lub wolno, ale wolno.

Jak mogę to naprawić?

Odpowiedz

10

Masz 250k wpisów na swojej liście zapytań IN. Nawet natywne zapytanie spowoduje umieszczenie bazy danych na kolanach. Oracle ogranicza listę zapytań IN do 1000 ze względu na wydajność, więc powinieneś zrobić to samo.

Podanie większej ilości pamięci RAM nie rozwiąże problemu, należy ograniczyć wybór/aktualizacje do maksymalnie 1000 wpisów za pomocą stronicowania.

Streaming is an option również, ale dla tak dużego zestawu wyników zwykle najlepszą opcją jest keyset pagination.

Jeśli możesz wykonać całe przetwarzanie w bazie danych, nie będziesz musiał przenosić 250k rekordów z bazy danych do aplikacji. Istnieje bardzo dobry powód, dla którego wiele RDBMS oferuje zaawansowane języki proceduralne (np. PL/SQL, T-SQL).

+0

Czy możesz mnie nauczyć trochę więcej? Mam niewielkie doświadczenie w interakcji z bazą danych Oracle. – Viet

+1

Musisz pobrać N wpisów, zaktualizować je, a następnie pobrać następną partia i tak dalej. –

+0

nadal jestem zdezorientowany, w moim zapytaniu "AKTUALIZUJ ... GDZIE ... IN (...) ", Lista zapytań jest niewielka i nie może osiągnąć 1000. I kiedy rozwijam się do drzewa drzewa Dominator w Eclipse MAT, znajduję moje zapytanie (" sqlQueryCheckSet "w moim kodzie), wiele z nich i myślę, że tylko it – Viet

1

Dziękuję Vlad Mihalcea z twoim linkiem do Hibernate issue, jest to błąd w hibernacji, naprawiono go w wersji 3.6. Aktualizuję wersję hibernacji w wersji 3.3.2 do wersji 3.6.10, używam domyślnej wartości "hibernate.query.plan_cache_max_soft_references" (2048), "hibernate.query.plan_cache_max_strong_references" (128), a mój problem zniknął. Nigdy więcej użycia pamięci.

3

Należy zauważyć, że nawet pomimo tego, że liczba obiektów w zapytaniuPlanCache może być skonfigurowana i ograniczona, prawdopodobnie nie jest to normalne.

W naszym przypadku pisaliśmy kwerendy w HQL podobny do tego:

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

Spowodowało n różnych zapytań przechodząc do queryPlanCache. Kiedy zmienił tę kwerendę do:

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

wielkość queryPlanCache została silnie zmniejszona od 100Mb do prawie 0. To drugie zapytanie jest tłumaczone w jednym preparedStament wynikającej tylko jeden obiekt wewnątrz pamięci podręcznej.

Powiązane problemy