我正在处理一个大型 ERP 项目,该项目具有包含大约 2100 个表的数据库模型。使用 Hibernate 映射的“仅”500 个表,部署在 Web 服务器上的应用程序需要大约 3GB 的工作内存。
在一个持久性单元中使用这么多表时,有什么方法可以减少 Hibernate 的元模型内存占用?还是我应该放弃 ORM 并使用普通的旧 JDBC(甚至 jOOQ)?
现在我正在使用 Hibernate 4.1.8、Spring 3.1.3、JBoss AS 7.1 并使用 MSSQL 数据库。
编辑:
JavaMelody memory histogram output - 生成了 2000 个测试表,这些测试表的范围比原始数据库模型小一些(因此“仅”消耗了 1.3GB 内存)
编辑 2:
Java MAT 堆分析:
最佳答案
打开的 hibernate session 将倾向于在使用时累积对象。这不是内存泄漏; hibernate session 被设计为一次请求使用,它缓存持久化的对象(即存在于 session 中),以及查询和其他数据。如果您调用 session.toString()
,您将看到 session 中存在的对象的洗衣 list 。
如果您处理大量对象,请考虑批量处理这些对象。您可以在每个批处理之后调用 session.clear()
以从 session 中清除缓存的数据和持久对象并减少 session 的内存占用(有时会显着)。
在调用 session.clear()
之后,请注意在此调用之前加载的对象将恢复到 detached 状态,并且对于当前 session 不再处于 Activity 状态。
您还可以使用 延迟获取 来优化 hibernate 为了处理给定操作而必须加载的数据量。您可以在 hibernate 文档中阅读更多相关信息。我建议启用 hibernate 的 SQL 日志记录功能,并检查 hibernate 是否正在拉回它不需要的数据。
您还可以配置 hibernate 以收集可以帮助您的统计信息:
sessionFactory.getStatistics().setStatisticsEnabled(true);
关于java - 大量表和 Hibernate 内存消耗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13567217/