有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

使用@batchsize后java jpa性能崩溃

我有一个java jpa/hibernate应用程序,需要获取大量数据才能执行其任务。我遇到了n+1问题,所以我决定使用hibernate。默认的\u batch\u fetch\u size(@batchsize)属性可降低所需的sql往返次数。我尝试了一些值,但几乎所有尝试的值的性能都崩溃了

batchsize:0-sqls发送:14000-持续时间:约1分钟

batchsize:4-sqls发送:5000-持续时间:10分钟以上

batchsize:10-sqls发送:2700-持续时间:约5分钟

batchsize:100-sqls发送:400-持续时间:约1分钟

这是一种“正常”行为吗?如果不是,会是什么错误

我用log4jdbc记录生成的sql。我注意到,每批语句之间都有大约1亿到1.5亿秒的延迟。如果我稍后运行sql,则每条语句的运行时间不超过20毫秒。因此,这不是与DB(语句中)相关的问题

Java:1.6.0_31,Hibernate 3.6.7,DB Postgres 9.1.1,JDBC postgresql-9.1-901。jdbc4。罐子

提前谢谢

更新 要澄清的是:性能损失是在批获取期间,而不是在批更新/插入期间


共 (1) 个答案

  1. # 1 楼答案

    经过一些调试,我发现了这个问题。Hibernate(至少在版本3.6.7中)将所有映射的集合存储在映射中。您可以使用如下snipplet访问这些地图:

    SessionImpl si = ((SessionImpl) entityManager.getDelegate());
    PersistenceContext persistenceContext = si.getPersistenceContext();
    persistenceContext.getCollectionEntries();
    

    因此,每个集合在该映射中创建一个条目。如果你有很多像我这样的收藏品的POJO,它会迅速扩大。例如,每32个集合加载10.000个POJO,您就有320.000个集合条目。Hibernate现在只需迭代映射(org.Hibernate.engine.BatchFetchQueue.getCollectionBatch(CollectionPersister,Serializable,int,EntityMode))来查找未加载的集合ID,以便稍后将其放入in子句中。Hibernate没有将对键的搜索限制在特定类型的集合中,因此这会变得更糟

    我想我必须清理一些集合,并希望hibernate能以更高效的方式在更高版本中找到密钥

    更新: 关于hibernate jira的这一评论对于有同样问题的人来说可能很有趣: https://hibernate.onjira.com/browse/HHH-1775?focusedCommentId=42686&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-42686

    更新: 这个问题在hibernate版本4.1.8中得到了解决