本章节我们讨论SQL高效分页问题。
1.1 数据准备
DROP TABLE TEST9;
CREATE TABLE TEST9 AS SELECT * FROM DBA_OBJECTS;
COMMIT;
alter table TEST9 add constraint PK_TEST9 primary key (OBJECT_ID);
1.2 低效分页
SELECT * FROM (
SELECT ROWNUM AS RN, T.* FROM TEST9 T ORDER BY T.OBJECT_ID ASC) T1
WHERE RN BETWEEN 1 AND 50;
我们只要前50条数据,但是,但是执行计划中是索引全扫描,也就是把数据全看了一遍。
当然这里可以强制走全表扫描,但是,不是最优的性能改善方法。我们先上高效版本,来个感官认识。
1.3 高效分页
SELECT T2.* FROM
(SELECT ROWNUM AS RN, T1.* FROM
(SELECT T.* FROM TEST9 T ORDER BY T.OBJECT_ID ASC) T1
WHERE ROWNUM <=50) T2
WHERE T2.RN>=1;
虽然我们这里也是索引全扫描,但是,实际 返回行数只有50条,因为执行计划ID=2的地方有COUNT STOPKEY,因为语句中有ROWNUM<=50,这样,检索数据是,首先利用索引有序的特点,进行索引全扫描,但是,走到第50条便返回,不再继续扫描。
但是假设我们看的不是前50页,而是50000~50050之间的数据呢?当然越来越慢,因为rownum<条数,就是需要扫描的条数,条数越大,扫描数量也越大,性能也就越差。