2013-07-18 18 views
0

我的进程存在性能问题。这是一个在CMT bean(在jboss服务器上)启动的异步任务。在一个线程中EJB事务减慢

1次迭代通过Hibernate执行1次更新和3次插入到我的数据库。该过程每隔100次迭代就会分成新的事务。

每次更新/插入之后都会在EntityManager上调用Flush。

虽然第一批的起始性能令人满意(大约5-8秒),但随着时间的推移,它会急剧下降。第30批大约需要30秒才能完成,后来每批生产超过2分钟。

我试着将FlushModeType切换到COMMIT,手动清除/关闭entityManagers,清理entityManagers缓存,我查找内存泄漏并找不到原因。

我测量了一小段代码执行时间,涉及数据库连接的每个代码都随着时间的推移而变慢。我知道一个事务处理越慢,处理的实体就越多,但为什么新事务也会变慢呢?

最新的流程包含250 000次迭代(1个线程中的2500个事务)并且永久结束。

如果需要,我会提供更多信息。任何帮助,将不胜感激。

我试过简化这段代码只做一个hibernate插入和没有其他操作,它仍然随着时间减慢。这是内部发生的一个抽象的伪视图。

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

原来这是一个java问题,我们在不同的配置下测试了我们的应用程序,当我们的jboss在java 1.7上运行时(与1.6相反),它工作正常。每批次在约5秒内完成。我们现在反对选择将我们的java升级到1.7,或者深入挖掘并发现我们在java 1.6上的设置有什么问题。

0

我确定我的建议可能不准确,或者您已经尝试过,但我想尝试一下。正如你所提到的,数据库连接是瓶颈,我会在那之后去做。

看完这个问题后,我发现交易所花费的时间与迭代次数成正比。因此,看起来在第一次迭代中创建的实体将在下一次迭代中发送到休眠。

例如,在第4次迭代中,在第1次,第2次和第3次迭代中创建的实体也被发送用于更新或以某种方式发送到休眠。

这可能是随着迭代过程性能下降的原因。随着更新/插入/选择的记录数量随着每次迭代而增加。

我可以在我的头顶认为以下几种可能性 - 在第一次迭代中使用

  1. Hibernate会话正在使用,直到结束。由于这个原因,在第一次迭代中创建的实体也将在后面的迭代中更新。我读到你尝试关闭实体经理等,但仍然请检查sesssion结束的地方。您可以在每次交易中创建新会话,或者在每次交易后删除在会话中创建的实体。

  2. 筛选每次迭代记录的列表是发送已处理的记录。这意味着列表应该在第3次迭代中发送从300到399的记录,但是从0到399的记录被发送到事务。

  3. 如果您使用HQL,请尝试使用命名查询。上次我使用Hibernate的时候(大约8个月前),我注意到当使用HQL时,hibernate加载的对象的数量远远多于命名查询。

Hibernate提供了一种打印发送到数据库的实际SQL查询/参数的方法。您可以检查发送到数据库的实际查询。对此的链接 - How to print a query string with parameter values when using Hibernate

+0

感谢您的回复,我必须补充说内部事务没有任何回应。我检查了以前迭代中的旧实体是垃圾收集的。在您回复之后,我试图在交易完成后明确清除/关闭会话,但没有任何更改。我还打印了hibernate SQL语句,并确认只有3个插入和1个更新完成。我想这意味着我现在必须找到一些解决方法,或者像Sameer Mali建议的那样切换到JDBC。 –

+0

我想建议在hibernate中使用自定义查询进行最后的尝试。这些在DB中执行。请参阅http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/querysql.html#querysql-cud这应该有助于您继续使用hibernate,并且在特定情况下不会切换到JDBC。 – Taps

0

在使用JPA执行批处理程序时,我们在几次遇到过类似的问题。 我们唯一能找到的解决方案是使用jdbc api来处理批量程序,这涉及到大量的处理。

+0

感谢您的回复,我会考虑切换到JDBC作为最后的希望解决方案。 –