在会话中加载实体后,Hibernate查询会大幅减慢

Ale*_*ait 11 hibernate hql

我正在使用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,这可能会有效.

  • 事实上,在我的代码中刷新模式被设置为自动。我已在报告代码上将刷新模式设置为 COMMIT,无论如何我们不会在那里创建任何实体。这有效地解决了性能问题。奇怪的是,仅对一个实体检查脏对象就花费了大约 60 毫秒。非常感谢您的见解! (2认同)

小智 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 获得