stackoverflow 上有很多关于如何正确执行分页的问题,对于 Oracle,最流行的答案是这样的:
select * from (
select row_.*, rownum rownum_
from (select * from some_table) row_
where rownum <= N)
where rownum_ > M;
我到处都看到过这个查询,Hibernate 也生成它用于分页。对于大多数情况来说这可能没问题,但它需要全表扫描,并且在处理大量数据时会显着减慢速度。
有一个提示应该有助于选择前 N 行
/*+ FIRST_ROWS(5000) */
但在选择第二页的情况下它没有帮助,并且似乎也使用完整扫描,至少这就是“解释计划”对我所说的。
为了解决这个问题,我目前正在实现自定义分页 - 读取表中所有行的 id 并将它们按范围拆分,以便分页查询看起来像这样:
select * from some_table where id between N and M;
我希望找到一个供应商解决这个问题,但到目前为止还没有成功。
所以,问题是 - 我是在重新发明轮子还是真的没有办法在不进行全面扫描的情况下在 Oracle 上实现分页?
更新:在 Oracle 12c 中,他们引入了一种新的分页语法:
OFFSET N ROWS FETCH NEXT M ROWS ONLY;
我已经尝试对此进行解释计划,它似乎只是一个别名
select * from (
select row_.*, rownum rownum_
from (select * from some_table) row_
where rownum <= N)
where rownum_ > M;
UPD2:刚刚发现类似的问题 - Oracle and Pagination 看来我之前在搜索重复项时不专心。所以,我的问题的答案很可能是否定的,但也许从那时起有些事情已经发生了变化......
最佳答案
首先:全表扫描并不总是问题。
- 在您的解释计划中检查不带分页的查询的成本
- 在分页解决方案中检查它
此外,当您进行测试时,请尝试使用具有高分页值的大表
补充要点:
- 没有排序的分页总是危险的,因为您无法确定 Oracle 为下一个“页面”提供结果的顺序 -> 可能无法重现结果
- 此外,在有序结果中,当前“ View ”之前的页面中的“新条目”可能会影响您的“下一页”
我异常(exception),您喜欢在数据库中“存储”查询并逐页获取数据,直到下划线数据发生变化?
关于Oracle查询结果分页无TABLE FULL SCAN数据访问方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29232846/