我正在尝试改善Asynk交易方法的性能。
在此任务中,我必须从表中读取几乎7500个记录,详细说明,然后在另一个表中插入/更新相应的行。
我正在使用Hibernate的Spring Data JPA。
为了使ScrollableResults
i将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();
}
执行时间变慢。..
大约需要600。我尝试修改我的Session
或EntityManager
的参数:session.setFlushMode(FlushModeType.COMMIT);
em.setFlushMode(FlushModeType.COMMIT);
它增加了性能并删除手动flush()方法该工作是在40年代完成的!!!
所以我的问题是:
-
session
或enityManager
上的setFlushMode
有什么区别? - 为什么
setFlushMode(FlushModeType.COMMIT);
以这种方式提高性能,而我只能通过手动冲洗实体才能具有相同的性能?
问题是默认的冲洗模式为 FlushModeType.AUTO
。在自动冲洗模式下,Hibernate将在每个查询之前冲洗(仅查询,找不到操作)。这意味着在您的上面示例中,默认情况下,每次致电getSingleResult()
时,Hibernate都在冲洗。之所以这样做,是因为您进行的更改可能会影响您的查询结果,因此Hibernate希望您的查询尽可能准确并首先冲洗。
您没有看到第一个示例中的性能打击,因为您只发出一个查询并滚动浏览它。我发现的最好的解决方案是您提到的,它只是将冲洗模式设置为COMMIT
。在Session
或EntityManager
上调用setFlushMode
之间没有区别。