Большое количество таблиц и потребление памяти Hibernate

Я работаю над большим проектом ERP, в котором есть модель базы данных с примерно 2100 таблицами. С «всего» 500 таблицами, отображаемыми с помощью Hibernate, приложение, развернутое на веб-сервере, занимает около 3 ГБ рабочей памяти.

Есть ли способ уменьшить объем памяти метамодели Hibernate при использовании такого количества таблиц в одной единице персистентности? Или мне просто отказаться от ORM и использовать старый добрый JDBC (или даже jOOQ)?

Сейчас я использую Hibernate 4.1.8, Spring 3.1.3, JBoss AS 7.1 и работаю с базой данных MSSQL.

Редактировать:

Вывод гистограммы памяти JavaMelody — с 2000 сгенерированными тестовыми таблицами, которые немного меньше по объему, чем исходная модель db (следовательно, «всего» 1,3 ГБ затраченной памяти)

Редактировать 2:

Анализ кучи Java MAT:


person Vedran    schedule 26.11.2012    source источник
comment
Знаете ли вы, сколько из 3 ГБ потребляется спящим режимом?   -  person Kai    schedule 26.11.2012
comment
Учитывая, что при использовании ~ 10 таблиц потребляемая память составляет менее 256 МБ, я бы посчитал, что это к северу от 2,74 ГБ :)   -  person Vedran    schedule 26.11.2012
comment
Хотите попробовать Batoo JPA? batoo.jp   -  person Hasan Ceylan    schedule 27.11.2012


Ответы (4)


Я столкнулся с той же проблемой, и я успешно уменьшил потребление памяти с xGB до 30M, проход buildSessionFactory с 2 минут до 7 секунд.

Важная часть решения размещена здесь

postInstantiate buildSessionFactory медленная/огромная база данных

person Nassim MOUALEK    schedule 04.06.2015

Открытый сеанс гибернации имеет тенденцию накапливать объекты по мере его использования. Это не утечка памяти; сеанс гибернации предназначен для однократного использования для запроса и кэширует объекты, которые являются постоянными (т. е. активными в рамках сеанса), а также запросы и другие данные. Если вы вызовете session.toString(), вы увидите подробный список объектов, которые живут в сеансе.

Если вы работаете с очень большим количеством объектов, рассмотрите возможность обработки объектов пакетами. Вы можете вызвать session.clear() после каждого пакета, чтобы удалить кэшированные данные и постоянные объекты из сеанса и уменьшить объем памяти, занимаемой сеансом (иногда значительно).

Имейте в виду, что после вызова session.clear() объекты, загруженные до этого вызова, вернутся в состояние detached и перестанут быть активными для текущего сеанса.

Вы также можете использовать ленивую выборку, чтобы оптимизировать объем данных, которые hibernate должен загрузить для обработки данной операции. Подробнее об этом можно прочитать в документации по hibernate. Я бы порекомендовал включить функцию ведения журнала SQL в спящем режиме и проверить, не извлекает ли спящий режим данные, которые ему не нужны.

Вы также можете настроить спящий режим для сбора статистики, которая может помочь вам:

sessionFactory.getStatistics().setStatisticsEnabled(true);
person RMorrisey    schedule 06.12.2012

Я бы посоветовал выполнить профилирование приложения в рабочей или промежуточной версии, используя мелодию Java, чтобы узнать, где или кто потребляет максимум памяти, и на основе результатов профилирования вы должны решить, какие изменения следует внести в приложение.

Мелодию Java очень легко интегрировать и настраивать, а в производстве вы можете включить или отключить, просто обновив web.xml.

person Jigar Parekh    schedule 26.11.2012
comment
Попробую сделать это и завтра обновлю вопрос с результатами, спасибо за предложение. - person Vedran; 26.11.2012
comment
Добавлена ​​гистограмма памяти из JavaMelody. - person Vedran; 29.11.2012
comment
из гистограммы многого не разобрать, но вы должны посмотреть, какой из ваших классов потребляет максимум памяти, а затем проверить, кто их держит. не уверен, что легко узнать использование памяти и ее узкое место. - person Jigar Parekh; 29.11.2012
comment
Да, и проблема в том, что я изначально предполагал. Добавлены выходные данные MAT для справки. - person Vedran; 30.11.2012
comment
из-за потребления памяти я думаю, что большая часть памяти удерживается фабрикой сеансов, вы используете какой-либо кеш? или загрузка множества объектов в контексте сохранения? - person Jigar Parekh; 03.12.2012
comment
Нет кеша 2-го уровня, это память, потребляемая при инициализации приложения, в которой нет ничего, кроме объектов JPA. - person Vedran; 03.12.2012

Какова цель вашего спящего объекта, спящий режим подходит только для CURD (создание, обновление, чтение, удаление), но не подходит для вычислений. для любой цели расчета (особенно перекрестной таблицы) лучше использовать процедуру хранения и ибатис вместе.

person ray_linn    schedule 06.12.2012
comment
Требованием проекта является ориентация на несколько РСУБД (например, Oracle, PGSQL, MSSQL, MySQL...), что, к сожалению, делает ibatis очень (ОЧЕНЬ!) дорогим вариантом. Кроме того, я очень не согласен с тем, что Hibernate подходит только для операций CRUD. - person Vedran; 06.12.2012