Oracle 分页查询总结 ( rownum )

改写于:   https://blog.csdn.net/fw0124/article/details/42737671    感谢博主

我只是选取自己需要的,你们想知道全部内容可以去访问以上链接,是篇非常好的博文

RowNum

可能都知道ROWNUM只适用于小于或小于等于,如果进行等于判断,那么只能等于1,不能进行大于的比较。
ROWNUM是oracle系统顺序分配为从查询返回的行的编号,返回的第一行分配的是1,第二行是2,依此类推。
ROWNUM总是从1开始,不管当前的记录是否满足查询结果,ROWNUM返回的值都是1,如果这条记录的值最终满足所有的条件,那么ROWNUM会递加,下一条记录的ROWNUM会返回2,否则下一条记录的ROWNUM仍然返回1。
理解了这一点,就清楚为什么一般的ROWNUM大于某个值或等于某个不为1的值是无法返回结果的,因此对于每条记录的ROWNUM都是1,而ROWNUM为1不满足查询的结果,所以下一条记录的ROWNUM不会递增,仍然是1,因此所有的记录都不满足条件。

验证:其实很容易理解,只能选择 ”小于” 才能得到 rownum的次序,如果 是 “大于”,那么 它会一直迭代的去找比它大的,然后把每一个 rownum 都设置成  “1”,因为 rownum 的每一个起点都是 “1”。而你需要的 rownum 大于 10,那么肯定就无法得到结果了

select org_name,rownum from TB_ORGANIZATION where rownum >= 10

 分页查询格式1
在查询的最外层控制分页的最小值和最大值。查询语句如下:

SELECT * FROM 
(
SELECT A.*, ROWNUM RN 
FROM (SELECT * FROM TABLE_NAME) A 
)
WHERE RN BETWEEN 21 AND 40

分页查询格式2

SELECT * FROM 
(
SELECT A.*, ROWNUM RN 
FROM (SELECT * FROM TABLE_NAME) A 
WHERE ROWNUM <= 40
)
WHERE RN >= 21

 分页查询格式3
考虑到多表联合的情况,如果不介意在系统中使用HINT的话,可以将分页的查询语句改写为:

SELECT /*+ FIRST_ROWS */ * FROM 
(
SELECT A.*, ROWNUM RN 
FROM (SELECT * FROM TABLE_NAME) A 
WHERE ROWNUM <= 40
)
WHERE RN >= 21

效率问题
对比这两种写法,绝大多数的情况下,第2个查询的效率比第1个高得多。
这是由于CBO优化模式下,Oracle可以将外层的查询条件推到内层查询中,以提高内层查询的执行效率。对于第2个查询语句,第二层的查询条件WHERE ROWNUM <= 40就可以被Oracle推入到内层查询中,这样Oracle查询的结果一旦超过了ROWNUM限制条件,就终止查询将结果返回了。
而第1个查询语句,由于查询条件BETWEEN 21 AND 40是存在于查询的第三层,而Oracle无法将第三层的查询条件推到最内层(即使推到最内层也没有意义,因为最内层查询不知道RN代表什么)。因此,对于第1个查询语句,Oracle最内层返回给中间层的是所有满足条件的数据,而中间层返回给最外层的也是所有数据。数据的过滤在最外层完成,显然这个效率要比第一个查询低得多。
上面分析的查询不仅仅是针对单表的简单查询,对于最内层查询是复杂的多表联合查询或最内层查询包含排序的情况一样有效。

观察上面格式1和格式2二者的执行计划可以发现,两个执行计划唯一的区别就是格式2的查询在COUNT这步使用了STOPKEY,也就是说,Oracle将ROWNUM <= 20推入到查询内层,当符合查询的条件的记录达到STOPKEY的值,则Oracle结束查询。因此,可以预见,采用第二种方式,在翻页的开始部分查询速度很快,越到后面,效率越低,当翻到最后一页,效率应该和第一种方式接近。

分页查询语句之所以可以很快的返回结果,是因为它的目标是最快的返回第一条结果。如果每页有20条记录,目前翻到第5页,那么只需要返回前100条记录都可以满足查询的要求了,也许还有几万条记录也符合查询的条件,但是由于分页的限制,在当前的查询中可以忽略这些数据,而只需尽快的返回前100条数据。这也是为什么在标准分页查询语句中经常会使用FIRST_ROWS提示的原因。
分页查询还有一个很明显的特点,就是处理的页数越小,效率就越高,越到后面,查询速度越慢。
 

小例子:

select * from (select rownum r,t.* from tb_organization t where rownum < 11) t2 where t2.r >5

猜你喜欢

转载自blog.csdn.net/qq_25221835/article/details/82784563