Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Large number of tables and Hibernate memory consumption

I'm working on a large ERP project which has database model with about 2100 tables. With "only" 500 tables mapped with Hibernate, application deployed on the web server takes about 3GB of working memory.

Is there any way to reduce Hibernate's metamodel memory footprint when using that many tables in one persistence unit? Or should I just give up on ORMs and go with plain old JDBC (or even jOOQ)?

Right now I'm using Hibernate 4.1.8, Spring 3.1.3, JBoss AS 7.1 and working with MSSQL database.

Edit:

JavaMelody memory histogram output - with 2000 generated test tables that are a bit smaller in scope from the original db model (hence 'only' 1.3GB of spent memory)

Edit 2:

Java MAT heap analysis:

  • Leak Suspects
  • Top Consumers
like image 611
Vedran Avatar asked Nov 26 '12 14:11

Vedran


2 Answers

An open hibernate session will tend to accrue objects as it is in use. This is not a memory leak; a hibernate session is designed to be used once for a request, and it caches objects that are persistent (i.e. live within the session), as well as queries and other data. If you call session.toString(), you will see a laundry list of objects that live in the session.

If you work with a very large number of objects, consider handling the objects in batches. You can call session.clear() after each batch to evict cached data and persistent objects from the session and reduce the session's memory footprint (sometimes dramatically).

After calling session.clear(), be aware that objects loaded before this call will revert to the detached state, and are no longer active for the current session.

You can also use lazy fetching to optimize the amount of data that hibernate has to load in order to handle a given operation. You can read more about this in the hibernate documentation. I would recommend enabling hibernate's SQL logging feature, and checking to see whether hibernate is pulling back data that it doesn't need.

You can also configure hibernate to gather statistics that can help you:

sessionFactory.getStatistics().setStatisticsEnabled(true);
like image 54
RMorrisey Avatar answered Nov 15 '22 21:11

RMorrisey


I would suggest to do profiling of application in production or staging using java melody to find out where or who is consuming maximum memory and based on profiling result you should decide on what changes should be done in application.

Java melody is very easy to integrate and configure and in production you can enable or disable by just updating web.xml

like image 23
Jigar Parekh Avatar answered Nov 15 '22 20:11

Jigar Parekh