我的流程存在性能问题。这是在CMT bean中启动的异步任务(在jboss服务器上)。
1次迭代通过Hibernate对我的数据库执行1次更新和3次插入。该过程每100次迭代分为新的事务。
每次更新/插入后都会在EntityManager上调用Flush。
虽然第一批的起始性能令人满意(约5-8秒),但随着时间的推移它会急剧减速。第30批需要大约30秒完成,后来每批增长超过2分钟。
我尝试将FlushModeType切换为COMMIT,手动清除/关闭entityManagers,清除entityManagers缓存,我查找内存泄漏并找不到这种减速的原因。
我测量了一小段代码执行时间,每个涉及数据库连接的代码都会随着时间的推移而减慢。我知道处理的实体越多,交易就越慢,但为什么新交易也会变慢?
最新的过程包括250 000次迭代(1个线程中的2500个事务),并且永远结束。
如果需要,我会提供更多信息。任何帮助将不胜感激。
我尝试简化此代码只是为了执行1次休眠插入而没有其他操作,它仍然会随着时间的推移而变慢。这是对内部发生的事情的抽象伪视图。
Bean1
@Asynchronous
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void mainTask(){
while(...){
subTask();
}
}
Bean2
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void subTask(){
100.times{
3*Insert
1*Update
}
}
答案 0 :(得分:0)
我确信我的建议可能不准确,或者您已经尝试过了,但我想尝试一下。正如你提到数据库连接是瓶颈,我会追求它。
在阅读问题后,我发现交易所花费的时间与迭代次数成正比。因此,看起来在第一次迭代中创建的实体在下一次迭代中被发送到休眠。
例如,在第4次迭代中,在第1次,第2次和第3次迭代中创建的实体也被发送以进行更新或以某种方式发送到休眠。
随着迭代的进行,这可能是性能下降的原因。随着每次迭代,要更新/插入/选择的记录数量会增加。
我可以想到以下几种可能性 -
第一次迭代中使用的Hibernate会话一直在使用到最后。因此,在第一次迭代中创建的实体也在以后的迭代中更新。我读到你试图关闭实体经理等。但是,请检查sesssion结束的地方。您可以在每个事务中创建新会话,也可以删除每次事务后在会话中创建的实体。
过滤每次迭代记录的列表是发送已处理的记录。这意味着列表应该在第3次迭代中将记录从300发送到399,但是从0到399的记录将被发送到事务。
如果您使用的是HQL,请尝试使用命名查询。上次当我使用Hibernate时(大约8个月后),我注意到当使用HQL时,hibernate加载的对象数远远超过命名查询。
Hibernate提供了一种打印发送给DB的实际SQL查询/参数的方法。您可以检查发送到DB的实际查询。链接 - How to print a query string with parameter values when using Hibernate
答案 1 :(得分:0)
在使用JPA执行批处理程序期间,我们在几次遇到类似的问题。 我们能找到的唯一解决方案是使用jdbc api进行批量程序,这涉及大量处理。
答案 2 :(得分:0)
原来这是一个java问题,我们在不同的配置上测试了我们的应用程序,当我们的jboss在java 1.7上运行时(与1.6相反),它工作正常。每批完成约5秒钟。我们现在反对选择将我们的java升级到1.7或深入挖掘并发现我们在java 1.6上的设置有什么问题。