2016-01-27 114 views
1

我们在我们的Web应用程序中使用Hibernate + Spring启动,我们遇到了EntityManager执行选择查询的性能问题。该查询应返回20行,并在DBArtisan中执行< 1秒。EntityManager.getResultList()的性能下降

CriteriaQuery<Long> totalCriteriaQuery = criteriaBuilder.createQuery(Long.class); 
     Root<M> totalRoot = totalCriteriaQuery.from(modelClass); 
     totalCriteriaQuery.select(criteriaBuilder.count(totalRoot)); 
     if (searchCriteria != null) { 
      totalCriteriaQuery.where(whereBuilder.build(searchCriteria, criteriaBuilder, totalRoot)); 
     } 
     TypedQuery<Long> totalQuery = em.createQuery(totalCriteriaQuery); 
     contentQuery.setFirstResult(pageRequest.getOffset()); 
     contentQuery.setMaxResults(pageRequest.getPageSize()); 
     StopWatch stopWatch = new StopWatch(); 
     stopWatch.start(); 
     List<M> resultList = contentQuery.getResultList(); 
     stopWatch.stop(); 
     System.out.println("Nano seconds: "+ stopWatch.getNanoTime()); 

我正在寻找的原因或使用EM性能的任何建议:然而,同样的查询9秒中的代码执行。

+0

比较SQL执行时间与HSQL并返回对象比较苹果和橙子。根据您的数据库使用分页速度非常慢,也为什么你使用分页这是一个总是变成单一结果的计数。 –

+0

您可以发布您在DBArtisan中运行的查询以及JPA正在生成的查询吗?除非他们是完全不同的查询,否则执行时间应该有显着差异。 –

+0

这是生成的JPA查询(稍作修改以便在DBArtisan中运行):select * from dummytable as generatedAlias0其中generatedAlias0.final_decision为null order by generatedAlias0.id asc - 返回20行 – enfany

回答

0

如果您的系统性能不佳,您应该尝试对代码进行分析,以查看性能问题真正存在的位置。我建议为此使用JProfiler,它会给出非常明确的结果,甚至可以报告调用者的功能。

您是否尝试过缓存查询,在您使用Hibernate + Spring配置时它可能也有帮助。如果你想提高你的表现JPA Performance Tuning,我建议看看这个页面。

P.S.根据我自己的经验,如果性能是您的第一选择,请尝试使用普通JDBC而不是EM。

0

在幕后,Criteria API使用OFFSET和LIMIT作为分页,但是那些don't scale用于较大的偏移值。

因此,随着页面的进一步发展,查询将变得越慢,但这是关系数据库的缺点。

您可以使用key-set pagination并首先获取id,然后使用它们来获取实体。

0

事实证明,我的实体与另一个表有一个连接列,由hibernate生成的实际查询包含多个子查询。我对该列有以下注释,一旦我改变为LAZY,它会按预期加快速度,但不知道更改FetchType的含义。

@ElementCollection(fetch = FetchType.EAGER) 
+1

不这样做。最好让它懒惰并使用[query-time FETCH JOIN](http://vladmihalcea.com/2014/12/15/eager-fetching-is-a-code-smell/)。 –