我想从大约40列和1.000.000行的表中获取所有数据,从偏移量到限制。我试图通过postgres为id列建立索引,并通过java和Entitymanager获取选择查询的结果。
我的查询大约需要1分钟才能得到我的结果,这有点太长了。我尝试使用其他索引,也将查询限制为100,但是这次仍然需要。我该如何解决?我需要一个更好的索引还是我的代码有问题?
CriteriaQuery<T> q = entityManager.getCriteriaBuilder().createQuery(Entity.class);
TypedQuery<T> query = entityManager.createQuery(q);
List<T> entities = query.setFirstResult(offset).setMaxResults(limit).getResultList();
答案 0 :(得分:1)
现在,您可能根本不使用索引。休眠限制/偏移量如何转换为数据库操作存在一些歧义(对于postgres,请参见this comment)。如对this post的回复中详细描述,这可能意味着开销。
如果您具有与offset和id列的值直接相关的偏移量,则可以在查询形式中使用它
SELECT e
FROM Entity
WHERE id >= offset and id < offset + limit
鉴于请求的记录数明显小于数据库将使用索引的表中的记录总数。
接下来的事情是,40列相当多。如果您实际上实际需要较少的资源,则可以仅使用所需的属性定义受限实体,然后查询该实体。这样应该会多一些开销。
如果您仍未达到性能要求,则可以选择执行jdbc连接/查询而不是使用休眠模式。
顺便说一句。您可以记录由jpa / hibernate发出的实际sql,并使用它从postgress获取execution plan,这将向您显示查询的实际状态以及是否使用索引。此外,您可以监视数据库的查询执行时间,以了解数据库消耗的处理时间的一部分,Java客户端消耗的处理时间以及数据传输开销。
答案 1 :(得分:0)
还有一种模仿偏移量+限制分页的技术,它使用基于页面第一条记录的 key 的分页。
Map<Integer, String> mapPageTopRecNoToKey = new HashMap<>();
然后搜索记录> =页面的键并加载页面大小+ 1条记录以找到下一页。
从第1页转到第5页会花费更多的精力,但仍会很快。
这当然是一个可怕的麻烦,但是当时的技术确实确实在某些数据库上提高了速度。
对于您而言,值得在jpql中指定所需的字段:select e.a, e.b
的速度要快得多。