使用@batchsize后jpa性能崩溃

moj*_*-de 4 java performance hibernate jpa

我有一个java jpa/hibernate应用程序需要获取大量数据来执行其任务.我遇到了n + 1问题,所以我决定使用hibernate.default_batch_fetch_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.我注意到每个批次声明之间的差距大约为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

提前致谢

更新以使事情清楚:性能损失是在批量提取期间而不是批量更新/插入

moj*_*-de 5

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

SessionImpl si = ((SessionImpl) entityManager.getDelegate());
PersistenceContext persistenceContext = si.getPersistenceContext();
persistenceContext.getCollectionEntries();
Run Code Online (Sandbox Code Playgroud)

因此,每个集合都会在此地图中创建一个条目.如果您拥有包含大量集合的pojos,就像我的情况一样,这会快速增长.例如,每个32个集合加载了10.000个pojos,你有320.000个集合条目.Hibernate现在只是迭代遍历map(org.hibernate.engine.BatchFetchQueue.getCollectionBatch(CollectionPersister,Serializable,int,EntityMode))来查找未加载的Collection id以便稍后将它们放在IN子句中.Hibernate不会将密钥的搜索限制为特定类型的集合,因此这会变得更糟.

我想我必须清理一些集合,希望hibernate能够更有效地找到更高版本的密钥.

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

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