在写这篇文章之前,对分页查询的认识就是经典的三层嵌套:第①层:获得需要的数据,第②层:用rownum限制展示数据的上限,第③层:用rownum的别名rn限制展示数据的下限。

在生产中遇见一个两层嵌套满足分页查询的SQL,兴奋之余拿出来与大家分享。分三步走1:创建测试表;2:经典分页查询展示SQL及执行计划;3:两层嵌套分页查询展示SQL及执行计划

1、创建测试表

SQL>CREATE TABLE TEST_A(ID NUMBER NOT NULL,SYSID NUMBER,STATUS NUMBER,INFO VARCHAR2(2000));
SQL>INSERT INTO TEST_A
SELECT ROWNUM,ROWNUM+1,TRUNC(DBMS_RANDOM.VALUE(1,9)) ,RPAD('*',2000,'*') FROM DUAL CONNECT BY ROWNUM<=100000;
SQL> ALTER table test_a add primary key(id);
SQL>create index ind_status_sysid on test_a(status,sysid);

说明:TEST_A中ID是主键,status字段取值[1,8]且均匀分布。
要求:取TEST_A中status=5的记录,按sysid排序,展示1-1000行。

2、经典分页查询展示SQL及执行计划

SQL> select /*+gather_plan_statistics*/* from
(select rownum rn ,t.* from
(select * from test_a where status=5 order by sysid )t
where rownum<=1000)
where rn >=1;

分析:
第①层获得status=5且按sysid排序的数据
第②层取返回数据的上限:rownum<=1000
第③层取返回数据的下限:rn>=1

查看SQL的执行计划

SQL> select * from table(dbms_xplan.display_cursor('','','allstats last'));

PLAN_TABLE_OUTPUT
SQL_ID 2dtgu07a19fhk, child number 0
-------------------------------------
select /*+gather_plan_statistics*/* from (select rownum rn ,t.* from
(select t.id,t.sysid,t.status from test_a t where status=5 order by
sysid )t where rownum<=1000) where rn >=1 Plan hash value: 503264694 -------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
-------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1000 |00:00:00.01 | 957 |
|* 1 | VIEW | | 1 | 1000 | 1000 |00:00:00.01 | 957 |
|* 2 | COUNT STOPKEY | | 1 | | 1000 |00:00:00.01 | 957 |
| 3 | VIEW | | 1 | 11186 | 1000 |00:00:00.01 | 957 |
| 4 | TABLE ACCESS BY INDEX ROWID | TEST_A | 1 | 11186 | 1000 |00:00:00.01 | 957 |
|* 5 | INDEX RANGE SCAN | IND_STATUS_SYSID | 1 | | 1000 |00:00:00.01 | 71 |
------------------------------------------------------------------------------------------------------------- Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("RN">=1)
2 - filter(ROWNUM<=1000)
5 - access("STATUS"=5) Note
-----
- dynamic statistics used: dynamic sampling (level=2) 30 rows selected. Elapsed: 00:00:00.04

分析:
Oracle满足条件的数据有1W多条,但是Oracle只取了1000条数据,从A-Rows中可以看出,大大提高了SQL的性能。
因为Oracle在执行SQL的时候会将查询条件推入到内层查询中,查到满足条件的1000条记录,就会返回,在执行计划COUNT STOPKEY上展示出来。

3:两层嵌套分页查询展示SQL及执行计划

SQL> select /*+gather_plan_statistics*/* from (select row_number()over(order by sysid) rn,t.* from test_a t where status=5) where rn between 1 and 1000;

SQL> select * from table(dbms_xplan.display_cursor('','','allstats last'));

PLAN_TABLE_OUTPUT

SQL_ID    cj0ds74naryn3, child number 0
-------------------------------------
select /*+gather_plan_statistics*/* from (select row_number()over(order
by sysid) rn,t.* from test_a t where status=5) where rn between 1 and
1000 Plan hash value: 1970407823 ------------------------------------------------------------------------------------------------------------
| Id | Operation | Name | Starts | E-Rows | A-Rows | A-Time | Buffers |
------------------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | | 1000 |00:00:00.01 | 957 |
|* 1 | VIEW | | 1 | 1000 | 1000 |00:00:00.01 | 957 |
|* 2 | WINDOW NOSORT STOPKEY | | 1 | 11186 | 1000 |00:00:00.01 | 957 |
| 3 | TABLE ACCESS BY INDEX ROWID | TEST_A | 1 | 11186 | 1000 |00:00:00.01 | 957 |
|* 4 | INDEX RANGE SCAN | IND_STATUS_SYSID | 1 | | 1000 |00:00:00.01 | 71 |
------------------------------------------------------------------------------------------------------------ Predicate Information (identified by operation id):
--------------------------------------------------- 1 - filter(("RN">=1 AND "RN"<=1000))
2 - filter(ROW_NUMBER() OVER ( ORDER BY "SYSID")<=1000)
4 - access("STATUS"=5) Note
-----
- dynamic statistics used: dynamic sampling (level=2) 29 rows selected. Elapsed: 00:00:00.03

分析:两层嵌套也达到了,查到满足1000条记录就返回的要求,逻辑读的消耗同样是957。
以上两种分页查询同时满足了取1000条符合条件的流水的目的,且效率高,可直接拿来用在生产中。

oracle优化-分页查询新认识的更多相关文章

  1. Oracle的分页查询语句优化

    Oracle的分页查询语句基本上可以按照本文给出的格式来进行套用. (一)   分页查询格式: SELECT * FROM  ( SELECT A.*, ROWNUM RN  FROM (SELECT ...

  2. Oracle中分页查询语句

    Oracle分页查询语句使我们最常用的语句之一,下面就为您介绍的Oracle分页查询语句的用法,如果您对此方面感兴趣的话,不妨一看. Oracle分页查询语句基本上可以按照本文给出的格式来进行套用.O ...

  3. Oracle 的分页查询 SQL 语句

    Oracle的分页查询语句基本上可以按照本文给出的格式来进行套用. 分页查询格式: SELECT * FROM (SELECT A.*, ROWNUM RN FROM (SELECT * FROM T ...

  4. Oracle 12C -- top-n查询新特性

    Oracle 12C -- top-n查询新特性在12C中,增加了一些新的特性.可以指定返回结果集的指定数量的行.或按照百分比返回行. SQL> select count(*) from emp ...

  5. Oracle 数据库分页查询的三种方法

    一.Oracle 数据库分页查询的三种方法 1.简介 不能对 rownum 使用 >(大于或等于 1 的数值).>=(大于 1 的数值).=(不等于 1 的数值),否则无结果.所以直接用 ...

  6. oracle 的分页查询与mysql 的分页查询

    oracle 的分页查询: select * from (select o.*,rownum rn  from Persons o) where rn >40 and rn <=60 : ...

  7. mysql、sql server、oracle数据库分页查询及分析(操作手册)

    1.mysql分页查询 方式1: select * from table order by id limit m, n; 该语句的意思为,查询m+n条记录,去掉前m条,返回后n条记录.无疑该查询能够实 ...

  8. oracle高效分页查询总结

    本文参考链接:http://blog.sina.com.cn/s/blog_8604ca230100vro9.html 探索查询语句: --分页参数:size = 20 page = 2 --没有or ...

  9. Oracle高效分页查询(转)

    page --没有order by的查询 -- 嵌套子查询,两次筛选(推荐使用) --SELECT * -- FROM (SELECT ROWNUM AS rowno, t.* -- FROM DON ...

  10. Oracle中分页查询语句的写法

    要动态的变化分页查询的条件,比如pageNow 这个变量表示的是当前是第几页, oracle分页有通用写法,假设一页5行 select * from ( select t.*,rownum rn fr ...

随机推荐

  1. C++面试八股文:了解sizeof操作符吗?

    某日二师兄参加XXX科技公司的C++工程师开发岗位第10面: 面试官:了解sizeof操作符吗? 二师兄:略微了解(不就是求大小的嘛..) 面试官:请讲以下如何使用sizeof? 二师兄:sizeof ...

  2. 推送服务接入指导(HarmonyOS篇)

    消息推送作为App运营日常使用的用户促活和召回手段,是与用户建立持续互动和连接的良好方式.推送服务(Push Kit)是华为提供的消息推送平台,建立了从云端到终端的消息推送通道,本文旨在介绍Harmo ...

  3. java解析CSV文件(getCsvData 解析CSV文件)

    首先需要下载opencsv的jar包 <!-- https://mvnrepository.com/artifact/com.opencsv/opencsv --> <depende ...

  4. 树莓派使用Golang+MQ135检测室内空气质量

      MQ135是一个比较便宜的空气质量传感器,可以用在家庭以及工业场所中.树莓派是一个小巧但很强大的卡片电脑,基于Linux,同时提供了很多硬件接口,方便开发出各种电子产品.Golang是一款简单高效 ...

  5. 使用JMeter连接达梦数据库的步骤和示例

    引言: 本文将介绍如何使用JMeter连接达梦数据库,并提供连接达梦数据库的步骤和示例,帮助您快速开始进行数据库性能测试. 步骤: 1. 下载并安装JMeter:首先,从JMeter官方网站下载并安装 ...

  6. 2021-3-13 xml的增删改查

    public void XmlAdd(string filename, List<People> pList) { try { List<People> peoples = X ...

  7. 自动刷新服务:nodemon

    安装命令: npm install -g nodemon 运行命令: nodemon server.js 运行结果:

  8. Redis从入门到放弃(6):持久化

    1.引言 Redis作为一种高性能的内存数据存储系统,常被用作缓存.会话存储.消息队列等多种应用场景.然而,由于其数据存储在内存中,一旦发生意外或服务器重启,数据就会丢失.为了保障数据的持久性和安全性 ...

  9. [elasticsearch]部署安装单节点和集群

    单点安装 进入安装目录:cd /usr/local 获取安装包: wget http://172.29.50.31/download/ProgramPackage/elasticsearch/elas ...

  10. 关于Openssh版本升级问题及版本升级到最新版8.7p1流程(CentOS7系统)

    前言: 对linux服务器做过漏洞扫描的都知道,常常服务器会被扫出一大堆关于openssh的漏洞,诸如下面这些,而其中的原因就是因为openssh版本比较低.于是就需要升级openssh的版本.下面就 ...