使用 Hibernate 时内存使用率高
Posted
技术标签:
【中文标题】使用 Hibernate 时内存使用率高【英文标题】:High memory usage when using Hibernate 【发布时间】:2014-08-13 02:09:17 【问题描述】:我编写了一个在 linux 服务器上运行 java 的服务器端应用程序。 我使用休眠打开数据库会话,使用本机 sql 查询它,并始终通过 try、catch、finally 关闭此会话。
我的服务器以非常高的频率使用休眠查询数据库。
我已经将 MaxHeapSize 定义为 3000M,但它通常在 RAM 上使用 2.7GB,它可以减少但比增加慢。有时它会增长到 3.6GB 的内存使用量,超过我在启动时定义的 MaxHeapSize。
当使用的内存为 3.6GB 时,我尝试使用 -jmap 命令转储它并得到一个大小仅为 1.3GB 的 heapdump。
我用eclipse MAT分析一下,这里是MAT的支配树 我认为休眠是问题所在,我有很多这样的 org.apache.commons.collections.map.AbstractReferenceMap$ReferenceEntry。它可能无法通过垃圾回收处理,或者可以但很慢。
我该如何解决?
【问题讨论】:
【参考方案1】:您的 IN 查询列表中有 250k 个条目。即使是本机查询也会使数据库瘫痪。出于性能原因,Oracle 将 IN 查询列表限制为 1000,因此您应该这样做。
给它更多的 RAM 并不能解决问题,您需要通过使用分页将您的选择/更新限制为最多 1000 个条目的批次。
Streaming
也是一个选项,但对于如此大的结果集,keyset pagination 通常是最佳选项。
如果您可以在数据库中完成所有处理,那么您就不必将 250k 记录从数据库移动到应用程序。许多 RDBMS 提供高级过程语言(例如 PL/SQL、T-SQL)是有充分理由的。
【讨论】:
你能再教我一点吗?我对oracle数据库交互的经验很少。 您需要获取 N 个条目,更新它们然后获取下一批,依此类推。 我仍然很困惑,在我的查询“UPDATE .. WHERE .. IN (...)”中,IN 查询列表很小,无法达到 1000。当我扩展到叶子时eclipse MAT中的支配树,我找到了我的选择查询(我的代码中的'sqlQueryCheckSet'),很多,我认为只有它 查看Hibernate issue。将“hibernate.query.plan_cache_max_soft_references”和“hibernate.query.plan_cache_max_strong_references”设置为一些适当的值。 太棒了。那么问题就得到了解答。【参考方案2】:感谢Vlad Mihalcea
提供指向Hibernate issue 的链接,这是休眠中的错误,已在 3.6 版中修复。我只是将我的休眠版本 3.3.2 更新到版本 3.6.10,使用“hibernate.query.plan_cache_max_soft_references”(2048)、“hibernate.query.plan_cache_max_strong_references”(128)的默认值,我的问题就消失了。不再有高内存使用。
【讨论】:
我面临着类似的性能问题,您将哪个模块升级到 3.6.10【参考方案3】:请注意,尽管可以配置和限制 queryPlanCache 中的对象数量,但拥有那么多可能并不正常。
在我们的例子中,我们在 hql 中编写类似于这样的查询:
hql = String.format("from Entity where msisdn='%s'", msisdn);
这导致 N 个不同的查询进入 queryPlanCache。当我们将此查询更改为:
hql = "from Blacklist where msisnd = :msisdn";
...
query.setParameter("msisdn", msisdn);
queryPlanCache 的大小从 100Mb 显着减少到几乎为 0。第二个查询被转换为一个单一的preparedStament,导致缓存中只有一个对象。
【讨论】:
以上是关于使用 Hibernate 时内存使用率高的主要内容,如果未能解决你的问题,请参考以下文章
Tomcat 的 Catalina 实用程序线程定期使用高 CPU 和内存
当我滚动 Flatlist 时,内存使用率越来越高,当我停止滚动时内存没有释放(React Native)
在 PyCharm 中分析 python 时内存使用率非常高