我正在努力改善我的asynk交易方法的表现。
在这个任务中,我必须从表中读取近7500条记录,详细说明,并在另一个表中插入/更新相应的行。
我正在使用spring数据jpa和hibernate。
为了获得ScrollableResults
我将EntityManager
注入我的服务。
这是我如何获取ScrollableResult
对象:
Session session = (Session) em.unwrap(Session.class);
ScrollableResults res = session.createQuery("from SourceTable s")
.setCacheMode(CacheMode.IGNORE)
.scroll(ScrollMode.FORWARD_ONLY);
while (res.next()){
.... // em.flush() called every 40 cycles
}
循环结果大约需要60秒。
这里是瓶颈。如果在我的循环中,我执行一个简单的查询:
query = em.createQuery("from DestTable d where d.item.id = :id", DestTable.class);
while (res.next()){
query.setParameter("id", myId).getSingleResult();
}
执行时间变得慢了x10 ..并且需要大约600秒。
我尝试修改Session
或我的EntityManager
的参数:session.setFlushMode(FlushModeType.COMMIT);
em.setFlushMode(FlushModeType.COMMIT);
它提高了性能并删除了手动flush()方法,工作在40年代完成!!!
所以我的问题是:
setFlushMode
或session
上致电enityManager
有何不同?setFlushMode(FlushModeType.COMMIT);
以这种方式增加性能,而且我只能通过手动刷新entityManager来获得相同的性能?答案 0 :(得分:5)
问题是默认刷新模式为FlushModeType.AUTO
。在自动刷新模式下,Hibernate将在每次查询之前刷新(仅查询,而不是查找操作)。这意味着在上面的示例中,默认情况下,每次调用getSingleResult()
时,Hibernate都会刷新。这样做的原因是因为您所做的更改可能会影响查询结果,因此Hibernate希望您的查询尽可能准确并首先刷新。
您在第一个示例中没有看到性能影响,因为您只发出一个查询并滚动浏览它。我找到的最好的解决方案是你提到的只是将刷新模式设置为COMMIT
的解决方案。在setFlushMode
或Session
上调用EntityManager
之间应该没有区别。