oracle 分页技术

概述
解析是什么意思呢? 就是分析的意思。

解析函数就是指能够完成某种复杂分析的函数,如求行号、求名次。这些函数可以拿来直接使用就可以完成复杂的分析任务。

首先学习Oracle解析函数的通用语法。先学习最简单的语法。
语法一:
解析函数() over(order by 字段 [desc])

说明:
over,英文意思就是“在……之上”。上面的语法整个意思就是指:“在排序的基础之上”进行的某种分析。
果解析函数是row_number()——行号,则表示是在某个字段排序的基础之上再求行号。
如果解析函数是rank()——名次,则表示是在某个字段排序的基础之上再求名次。

示例一:根据工资降序排序,显示行号及员工信息。
select row_number() over(order by sal desc) as 行号,
       empno,ename,sal
from emp;
返回:
行号 EMPNO ENAME     SAL
1     7839     KING      5000.00
2     7902      FORD    3000.00
3     7566     JONES 2975.00
……
对比使用rownum来得行号的sql语句:
select rownum as 行号,t.*
from (select empno,ename,sal from emp order by sal desc ) t

发现使用row_number()会没有使用嵌套子查询。

示例二:根据工资降序排序,并显示第4行到第6行的员工信息。
分析:
需要先在子查询中产生行号,然后再对行号进行过滤。
select * from (
select empno,ename,sal,
       row_number() over(order by sal desc) as 行号
from emp
) t
where t.行号 between 4 and 6

对比使用rownum来得行号的sql语句:
select * from (
select rownum as 行号,t.*
from (select empno,ename,sal from emp order by sal desc ) t
)
where t.行号 between 4 and 6

使用row_number()最大的原因并不是因为少写了一层子查询,而是因为数据量比较大的时候,如上千万条记录,分页的效率非常高。

测试案例

--目标:产生上千万的模拟数据
create sequence my_seq;
create table emp2
as
select my_seq.nextval as empno, ename, job, mgr, hiredate, sal, comm, deptno
from emp;

--反复复制自身数据
insert into emp2
select my_seq.nextval as empno, ename, job, mgr, hiredate, sal, comm, deptno
from emp2;
commit;

至少产生1千万条记录以后再继续后面的操作。

问题:为什么下面的sql执行很慢?
select count(*) from emp2;
分析:因为emp2是通过复制表得到的,没有主键索引。所以count(*)是查询的原始表emp2,而emp2表中的数据量非常大。
解决:在emp2表上建立主键。
alter table EMP2 add constraint pk_emp2 primary key (EMPNO);

解释:修改emp2表,增加一个名称为“pk_emp2”约束,类型为主键,主键字段是empno。
“pk_emp2”是一个自定义名称,其中“pk”是主键的简称,通常后面跟表名。

说明:这种alter语句可以直接利用在PLSQL Developer工具的操作来得到,不需要死记。

现在执行count(*),时间就会非常快了。

对比下面两种sql运行的时间:
·根据empno降序排序,分别使用rownum和row_number()分页,取第2页,每页100条。
代码参考:
--使用rownum
SELECT *
FROM (SELECT ROWNUM NO, t.*
          FROM (SELECT * FROM emp2 ORDER BY empno DESC) t)
WHERE NO BETWEEN 101 AND 200;

说明:应该是几十秒到上百秒。

--使用row_number()
select * from
(
select row_number() over(order by empno desc) 行号,
       empno,ename,sal from emp2
) a
where a.行号 between 101 and 200

说明:正常情况下应该不到1秒。


大数据量高效分页小结
1、要在排序的字段上建立索引
2、使用Oracle解析函数:row_number()

对比试验:
删除主键约束pk_emp2,对应的索引也会被删除。再记录程序的运行时间。
alter table EMP2
drop constraint PK_EMP cascade;

说明:没有了索引,row_number的效率会降低非常多。


问题:row_number好像越到后面会越慢?
回答:
是的。如执行下面的SQL语句:
select * from
(
select row_number() over(order by empno desc) 行号,
       empno,ename,sal from emp2
) a
where a.行号 between 10000000 and 10000100
执行:50秒左右(具体的时间与机器配置有关)

分析:实际上,分页以后最关心的数据就是放在最前面,
分页以后取到后面上万页的情况也不是很实际。
这也是我所体会到Oracle是最聪明的数据库之一:用户关心的数据,查询就快!

说明:
·在真正的分页程序中,必须指定排序的字段,记录的前后顺序才能确定下来。
·所以分页之前必须指定先按哪个字段来排序。

你可能感兴趣的:(oracle 分页技术)