Высокое использование памяти при использовании Hibernate

я кодирую серверное приложение с java, запущенным на сервере linux. Я использую hibernate для открытия сеанса в базу данных, использую собственный sql для запроса и всегда закрываю этот сеанс try, catch, finally.

мой сервер запроса DB с использованием спящего режима с очень высокой частотой.

Я уже определяю MaxHeapSize для него 3000M, но обычно он использует 2.7 GB в ОЗУ, он может уменьшаться, но медленнее, чем увеличиваться. Когда-нибудь он вырастет до использования памяти 3.6 GB, больше, чем мой MaxHeapSize определить, когда начать.

когда используется память 3.6 GB, я пытаюсь сбросить ее с помощью команды-jmap и получил heapdump размером только 1.3 GB.

Im с помощью eclipse MAT для его анализа, вот дерево доминатора из мата Dominator tree Я думаю, что проблема в спящем режиме, у меня так много организаций.апаш.палата общин.коллекции.карта.AbstractReferenceMap$ReferenceEntry как это. Возможно, он не может быть утилизирован сборкой мусора или может, но медленно.

Как я могу это исправить?

3 ответов


вы 250k записи в списке запросов. Даже собственный запрос поставит базу данных на колени. Oracle ограничивает список in query 1000 по соображениям производительности, поэтому вы должны сделать то же самое.

предоставление ему больше ОЗУ не решит проблему, вам нужно ограничить выбор/обновления пакетами не более 1000 записей, используя разбиение на страницы.

Streaming-это вариант также, но, для такого большого результирующего набора, разбиение на страницы keyset обычно лучший вариант.

Если вы можете сделать всю обработку в базе данных, то вам не придется перемещать 250k записей из БД в приложение. Существует очень веская причина, по которой многие СУБД предлагают расширенные процедурные языки (например, PL/SQL, T-SQL).


обратите внимание, что даже несмотря на то, что количество объектов в queryPlanCache может быть настроено и ограничено, это, вероятно, не нормально иметь так много.

в нашем случае мы писали запросы в hql, похожие на это:

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

это привело к N различным запросам, идущим в queryPlanCache. Когда мы изменили этот запрос:

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

размер queryPlanCache был резко уменьшен со 100 МБ до почти 0. Этот второй запрос переведен в один preparedStament в результате только один объект внутри кэша.


спасибо Vlad Mihalcea со ссылкой на проблема спящего режима, это ошибка в спящем режиме, она исправлена в версии 3.6. Я просто обновляю hibernate версии 3.3.2 до версии 3.6.10, используя значение по умолчанию "hibernate.запрос.plan_cache_max_soft_references "(2048), " спящий режим.запрос.plan_cache_max_strong_references " (128), и моя проблема исчезла. Больше нет высокой памяти.