我正在使用Hibernate EntityManager,并且在我的Hibernate查询中遇到了奇怪的减速.看看这段代码:
public void testQuerySpeed() {
for(int i = 0; i < 1000; i++) {
em.createNativeQuery("SELECT 1").getResultList();
}
}
Run Code Online (Sandbox Code Playgroud)
这在我的机器上运行大约750毫秒.考虑到它只是选择一个恒定的整数,但不是很快,但可以接受.在我启动查询之前,我的问题出现在我的EntityManager会话中加载了任何实体:
public void testQuerySpeed() {
CommercialContact contact = em.find(CommercialContact.class, 1890871l);
for(int i = 0; i < 1000; i++) {
em.createNativeQuery("SELECT 1").getSingleResult();
}
}
Run Code Online (Sandbox Code Playgroud)
em.find()很快,但运行时1000查询增加了十倍以上,大约10秒.如果我把它放在em.clear()后面em.find(),问题就会再次消失,运行时间会回到750ms.
我在这里使用了本机查询,但HQL查询也存在问题.当实体在EntityManager会话中时,似乎所有查询至少需要70ms.
在生成需要n + 1个查询的列表时,这种性能下降确实在伤害我们.
我已经测试了最新的Hibernate 3.5 beta,并且遇到了完全相同的问题.有没有人看过这个问题,或者有任何想法如何解决它?
我正在使用PostgreSQL 8.3,使用资源本地事务(在Tomcat中运行).使用内置连接池,但使用C3P0没有区别.
Bry*_*anD 13
我还必须建议使用JVM分析器来查看时间的去向.打开Hibernate会话的SQL语句记录也可能没有什么坏处,只是为了确保你没有运行比你想象的更多的SQL.
这里首先想到的是Hibernate Session的"刷新"行为.您是否在Session上明确设置了特定的刷新模式?如果没有,那么你会得到"自动"刷新,这会对会话中的对象进行一些检查,以确定是否存在需要"刷新"回数据库的内存更改(在事务内部) , 当然).
我想首先尝试查看它是否有任何影响的最简单方法是修改上面显示的测试代码,以指定在提交数据库事务时要手动进行刷新:
public void testQuerySpeed() {
em.setFlushMode(FlushModeType.COMMIT); // assuming you're using JPA annotations
CommercialContact contact = em.find(CommercialContact.class, 1890871l);
for(int i = 0; i < 1000; i++) {
em.createNativeQuery("SELECT 1").getSingleResult();
}
}
Run Code Online (Sandbox Code Playgroud)
我想的另一个想法是询问您是否可以在单独的EntityManager中执行批量任务,如果您只是在进行UPDATE或INSERT,这可能会有效.
小智 5
我有本质上相同的问题(在循环内查询)。我使用 JProfiler 进行了分析验证……我感兴趣的方法的执行花费了 572 秒,而这次休眠脏检查花费了 457 秒(大约 80%)。很神奇,不是吗?我必须说我有很多实体由 EntityManager 管理。如果我在违规代码中引入 em.flush()/em.clear() 或 em.setFlushMode(FlushModeType.COMMIT),性能问题就会消失。
探查器结果可在http://img1.imagive.com/0110/hibernate_dirty_checking_bad_perfomances0ce.png 获得
| 归档时间: |
|
| 查看次数: |
11886 次 |
| 最近记录: |