我有一个java jpa/hibernate应用程序,它需要获取大量数据来执行其任务。我遇到了n+1问题,所以我决定使用hibernate.default_batch_fetch_size (@batchsize)属性来降低所需的sql往返时间。我尝试了一些值,但几乎所有尝试过的值都崩溃了。
批量大小:0- sqls发送: 14000 -时长:约1分钟
批量大小:4- sqls发送: 5000 -时长:超过10分钟
批量大小: 10 - sqls发送: 2700 -持续时间:约5分钟
批量大小: 100 - sqls发送: 400 -时长:约1分钟
这是一种“正常”行为吗?如果不是,那会是什么错误呢?
我用log4jdbc记录了生成的sql。我注意到每个批处理语句之间的间隔约为100-150毫秒。如果我稍后运行sql,则每个语句的运行时间不超过20毫秒。所以这并不是一个与DB (IN语句)相关的问题。
Java: 1.6.0_31,Hibernate 3.6.7,DB Postgres 9.1.1,JDBC postgresql-9.1-901.jdbc4.jar
提前感谢
更新说明:性能损失是在批处理获取期间,而不是在批处理更新/插入期间
发布于 2012-06-04 22:23:31
经过一些调试,我发现了问题所在。Hibernate (至少在3.6.7版本中)将所有映射的集合存储在一个map中。您可以使用如下所示的代码片段访问这些映射:
SessionImpl si = ((SessionImpl) entityManager.getDelegate());
PersistenceContext persistenceContext = si.getPersistenceContext();
persistenceContext.getCollectionEntries();所以每个集合在这个map.If中创建一个条目,你有一个包含很多集合的pojos,就像我的例子一样,它很快就变大了。例如,每32个集合加载10.000个pojo,就有320.000个集合条目。Hibernate现在只是迭代映射( (org.hibernate.engine.BatchFetchQueue.getCollectionBatch(CollectionPersister,Serializable,int,EntityMode)来查找未加载的集合in,以便稍后将这些IN放入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中解决
https://stackoverflow.com/questions/10834573
复制相似问题