我正在努力提高我的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来获得相同的性能?
Pace.. 5
问题是默认的刷新模式是FlushModeType.AUTO
.在自动刷新模式下,Hibernate将在每次查询之前刷新(仅查询,而不是查找操作).这意味着在上面的示例中,默认情况下,每次调用时Hibernate都会刷新getSingleResult()
.这样做的原因是因为您所做的更改可能会影响查询结果,因此Hibernate希望您的查询尽可能准确并首先刷新.
您没有在第一个示例中看到性能损失,因为您只发出一个查询并滚动浏览它.我找到的最好的解决方案是你提到的只是将刷新模式设置为COMMIT
.应该有打电话没有任何区别setFlushMode
的Session
或EntityManager
.
问题是默认的刷新模式是FlushModeType.AUTO
.在自动刷新模式下,Hibernate将在每次查询之前刷新(仅查询,而不是查找操作).这意味着在上面的示例中,默认情况下,每次调用时Hibernate都会刷新getSingleResult()
.这样做的原因是因为您所做的更改可能会影响查询结果,因此Hibernate希望您的查询尽可能准确并首先刷新.
您没有在第一个示例中看到性能损失,因为您只发出一个查询并滚动浏览它.我找到的最好的解决方案是你提到的只是将刷新模式设置为COMMIT
.应该有打电话没有任何区别setFlushMode
的Session
或EntityManager
.