我们在Web应用程序中使用Hibernate + Spring启动,我们在EntityManager中遇到性能问题以执行选择查询。该查询应返回20行并执行<在DBArtisan 1秒。但是,在代码中执行相同的查询9秒:
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的原因或有关性能的任何建议。
答案 0 :(得分:0)
如果您遇到性能不佳,则应尝试分析代码以查看性能问题的确切位置。我建议使用JProfiler来实现这个目的,它提供了非常清晰的结果,甚至报告了调用者函数。
您是否尝试过缓存查询,在使用Hibernate + Spring配置时它也可能有所帮助。如果您想提高效果JPA Performance Tuning,我建议您查看此页面。
P.S。根据我自己的经验,如果性能是您的第一选择,请尝试使用普通JDBC而不是EM。
答案 1 :(得分:0)
在幕后,Criteria API使用OFFSET和LIMIT进行分页,但don't scale用于大偏移值。
因此,随着页面的进一步发展,查询将变得越慢,但这是关系数据库的缺点。
您可以先使用key-set pagination并获取ID,然后使用这些来获取实体。
答案 2 :(得分:0)
事实证明我的实体有一个带有另一个表的连接列,hibernate生成的实际查询包含多个子查询。我为该列添加了以下注释,一旦我更改为LAZY,它会按预期加速,但不确定更改FetchType的含义。
@ElementCollection(fetch = FetchType.EAGER)