代码之家  ›  专栏  ›  技术社区  ›  Alexander Malfait

在会话中加载实体后,Hibernate查询速度急剧降低

  •  11
  • Alexander Malfait  · 技术社区  · 16 年前

    我正在使用Hibernate EntityManager,并且在Hibernate查询中遇到了奇怪的减速。请看下面的代码:

    public void testQuerySpeed() {
        for(int i = 0; i < 1000; i++) {
            em.createNativeQuery("SELECT 1").getResultList();
        }
    }
    

    public void testQuerySpeed() {
        CommercialContact contact = em.find(CommercialContact.class, 1890871l);
    
        for(int i = 0; i < 1000; i++) {
            em.createNativeQuery("SELECT 1").getSingleResult();
        }
    }
    

    em.clear() 之后 em.find()

    我在这里使用了本机查询,但HQL查询也存在问题。似乎只要实体在EntityManager会话中,所有查询都至少需要70毫秒。

    在生成需要n+1查询的列表时,这种性能下降确实会对我们造成伤害。

    我已经测试了最新的Hibernate 3.5测试版,并且遇到了完全相同的问题。有没有人见过这个问题,或者对如何解决它有什么想法?

    我正在使用PostgreSQL 8.3,使用资源本地事务(在Tomcat中运行)。使用内置连接池,但使用C3P0没有任何区别。

    3 回复  |  直到 16 年前
        1
  •  14
  •   BryanD    16 年前

    我还建议使用JVM分析器来查看时间的走向。为Hibernate会话打开SQL语句日志记录,只是为了确保您运行的SQL没有超出您的想象,这可能也没有什么坏处。

    首先想到的是Hibernate会话的“刷新”行为。您是否在会话上明确设置了特定的刷新模式?如果没有,那么您将得到“自动”刷新,这将对会话中的对象进行一定量的检查,以确定内存中是否有需要“刷新”回数据库的更改(当然是在事务内部)。

    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();
        }
    }
    

    我的另一个想法是询问您是否可以在一个单独的EntityManager中执行批量任务,如果您只是在进行更新或插入,它就可以工作。

        2
  •  5
  •   user260112 user260112    16 年前

    我基本上遇到了相同的问题(在循环中查询)。我用JProfiler进行了一次分析验证……我感兴趣的方法的执行耗时572秒,hibernate脏检查耗时457秒(约80%)。太棒了,不是吗?我必须说,我有很多实体由EntityManager管理。如果我在有问题的代码中引入em.flush()/em.clear()或em.setFlushMode(FlushModeType.COMMIT),性能问题就会消失。

    http://img1.imagilive.com/0110/hibernate_dirty_checking_bad_perfomances0ce.png

        3
  •  1
  •   Max Rydahl Andersen    16 年前

    您执行的本机查询没有说明它将涉及什么,因此Hibernate必须(为了一致性起见)对它所知道的所有表中的所有数据进行flush()(并且您的单个find()可能已经获取了不止一个对象,因此它可能不是一个简单的操作)。