做开发的,或者一些新手对分页应该不模糊,也是平常使用的最多的一个功能。现在比较一些主要的分页方式:
1.使用rownum的 分页
select ename,deptno from (
select ename,deptno,rn from ( select ename,deptno,rownum rn from emp order by deptno ) where rownum between 12 and 24 )这种分页一看就比较差,使用了between and 这种比较差的谓词,还有一个缺点就是
在层层嵌套的过程,都需要把 业务需要的数据列的投影取出来,这也是影响效率的,还好
oracle 是行式数据库,这一点影响还不大。
2.
select ename,deptno from
(select ename,deptno,rn from (select ename,deptno,rownum rn from emp where rownum<12 )where rn>5)这种分页 是大家使用的最多的一种分页方式,没有什么好说的。
3.
select /*+ first_row()*/ ename,deptno from
(select ename,deptno,rn from (select ename,deptno,rownum rn from emp where rownum<12 )where rn>5)这种就比较上境界了,如果你的系统是oltp系统的话,系统默认的CBO是all_row() 的方式,而分页是
特别不适合这种方式的,加上这个hint的话就完美了,兼顾了两者的优劣势。
4.根据 RowId 来分页
select
where ename,deptno from empwhere rowid in( select rowid from ( select rowid,rownum,rowid,deptno from (select deptno,rowid from emp order by deptno ) where rownum <12 ) where rownum >5 ))这种分页 解决了我们在1,2中遇到的问题,也就是直到最后一层才进行数据的垂直映射。效率就提高了,但是又有一个问题,在排序时是要取出排序列的, deptno 不是主键,是外键,有外键索引,而且是数字,问题不大。但是如果是时间等不是索引的话,
的话在上面查找排序,也是一样效率不好的。
5. 使用分析函数来做分页
select * from (
select * ,row_number() over (order by deptno) rk from emp) where rk<16 and rk>5)这种分页最简单,同时也是效率最低的,