关于分页的高效写法

creat table test as select * from dba_objects;

SQL> create index ind_test on test(owner,object_type,created);

SQL> set autot traceonly;
SQL> select * from (select rownum rn,object_id,object_name,subobject_name,status from (select object_id,object_name,subobject_name,status from test where wner='SYS' and object_type='TABLE' order by created desc) where rownum<=50) t where rn>=1;

50 rows selected.


Execution Plan
----------------------------------------------------------
Plan hash value: 1950179327

--------------------------------------------------------------------------------------------
| Id  | Operation                       | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |          |    50 |  5700 |     6   (0)| 00:00:01 |
|*  1 |  VIEW                           |          |    50 |  5700 |     6   (0)| 00:00:01 |
|*  2 |   COUNT STOPKEY                 |          |       |       |            |          |
|   3 |    VIEW                         |          |   724 | 73124 |     6   (0)| 00:00:01 |
|   4 |     TABLE ACCESS BY INDEX ROWID | TEST     |   724 | 99912 |     6   (0)| 00:00:01 |
|*  5 |      INDEX RANGE SCAN DESCENDING| IND_TEST |    51 |       |     3   (0)| 00:00:01 |                    
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN">=1)
   2 - filter(ROWNUM<=50)
   5 - access("OWNER"='SYS' AND "OBJECT_TYPE"='TABLE')
       filter("OWNER"='SYS' AND "OBJECT_TYPE"='TABLE')

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         26  consistent gets
          0  physical reads
          0  redo size
       2934  bytes sent via SQL*Net to client
        502  bytes received via SQL*Net from client
          5  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
         50  rows processed

从上面执行计划来看,是正确地利用了索引。这里是第1页的数据,那么取中间页数据来看呢?
SQL> select * from (select rownum rn,object_id,object_name,subobject_name,status from (select object_id,object_name,subobject_name,status from test where wner='SYS' and object_type='TABLE' order by created desc) where rownum<=49000) t where rn>=48951;

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 1950179327

--------------------------------------------------------------------------------------------
| Id  | Operation                       | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |          |   724 | 82536 |    41   (0)| 00:00:01 |
|*  1 |  VIEW                           |          |   724 | 82536 |    41   (0)| 00:00:01 |
|*  2 |   COUNT STOPKEY                 |          |       |       |            |          |
|   3 |    VIEW                         |          |   724 | 73124 |    41   (0)| 00:00:01 |
|   4 |     TABLE ACCESS BY INDEX ROWID | TEST     |   724 | 99912 |    41   (0)| 00:00:01 |
|*  5 |      INDEX RANGE SCAN DESCENDING| IND_TEST |   724 |       |     6   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN">=48951)
   2 - filter(ROWNUM<=49000)
   5 - access("OWNER"='SYS' AND "OBJECT_TYPE"='TABLE')
       filter("OWNER"='SYS' AND "OBJECT_TYPE"='TABLE')

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
         13  recursive calls
          0  db block gets
        212  consistent gets
          0  physical reads
          0  redo size
        591  bytes sent via SQL*Net to client
        458  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

这里的一致读取达到了212,翻了近十倍,这里48950有条回表了,没有返回给客户,这样就造成了浪费。那么我们怎么避免这样的浪费呢?我们可以利用相同的索引,但是在索引上面先排好序,再分页,选择完ROWID,再回表查询。

SQL> select /*+ ordered use_nl(t,test)*/ object_id,object_name,subobject_name,status from (select rid from (select rownum rn,rid from (select rowid rid from test where wner='SYS' and object_type='TABLE' order by created desc) where rownum<=49000 ) where rn >=48951 ) t,test where t.rid=test.rowid;

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 1867647190

--------------------------------------------------------------------------------------------
| Id  | Operation                       | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                |          |   724 | 99912 |   731   (1)| 00:00:09 |
|   1 |  NESTED LOOPS                   |          |   724 | 99912 |   731   (1)| 00:00:09 |
|*  2 |   VIEW                          |          |   724 | 18100 |     6   (0)| 00:00:01 |
|*  3 |    COUNT STOPKEY                |          |       |       |            |          |
|   4 |     VIEW                        |          |   724 |  8688 |     6   (0)| 00:00:01 |
|*  5 |      INDEX RANGE SCAN DESCENDING| IND_TEST |   724 | 35476 |     6   (0)| 00:00:01 |
|   6 |   TABLE ACCESS BY USER ROWID    | TEST     |     1 |   113 |     1   (0)| 00:00:01 |
--------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   2 - filter("RN">=48951)
   3 - filter(ROWNUM<=49000)
   5 - access("OWNER"='SYS' AND "OBJECT_TYPE"='TABLE')
       filter("OWNER"='SYS' AND "OBJECT_TYPE"='TABLE')

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          6  consistent gets
          0  physical reads
          0  redo size
        531  bytes sent via SQL*Net to client
        458  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed

先分页再回表的,看吧,这就是效果。COOL

下面用我现在项目中用到的ROW_NUMBER()来做一下实验对比

SQL> select object_id,object_name,subobject_name,status from (select object_id,object_name,subobject_name,status,row_number() over(order by created desc)rn  from test  where wner='SYS' and object_type='TABLE' ) where rn between 48951 and 49000;

no rows selected


Execution Plan
----------------------------------------------------------
Plan hash value: 835048009

-------------------------------------------------------------------------------------------
| Id  | Operation                      | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT               |          |   724 | 82536 |    42   (3)| 00:00:01 |
|*  1 |  VIEW                          |          |   724 | 82536 |    42   (3)| 00:00:01 |
|*  2 |   WINDOW NOSORT STOPKEY        |          |   724 | 99912 |    42   (3)| 00:00:01 |
|   3 |    TABLE ACCESS BY INDEX ROWID | TEST     |   724 | 99912 |    41   (0)| 00:00:01 |
|*  4 |     INDEX RANGE SCAN DESCENDING| IND_TEST |   724 |       |     6   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - filter("RN">=48951 AND "RN"<=49000)
   2 - filter(ROW_NUMBER() OVER ( ORDER BY INTERNAL_FUNCTION("CREATED") DESC
              )<=49000)
   4 - access("OWNER"='SYS' AND "OBJECT_TYPE"='TABLE')
       filter("OWNER"='SYS' AND "OBJECT_TYPE"='TABLE')

Note
-----
   - dynamic sampling used for this statement


Statistics
----------------------------------------------------------
          7  recursive calls
          0  db block gets
        140  consistent gets
          0  physical reads
          0  redo size
        531  bytes sent via SQL*Net to client
        458  bytes received via SQL*Net from client
          1  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          0  rows processed
效果还好,不过还是用先索引排序分页,再回表的效果最后

 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/21158541/viewspace-669948/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/21158541/viewspace-669948/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
校园失物招领系统管理系统按照操作主体分为管理员和用户。管理员的功能包括字典管理、论坛管理、公告信息管理、失物招领管理、失物认领管理、寻物启示管理、寻物认领管理、用户管理、管理员管理。用户的功能等。该系统采用了Mysql数据库,Java语言,Spring Boot框架等技术进行编程实现。 校园失物招领系统管理系统可以提高校园失物招领系统信息管理问题的解决效率,优化校园失物招领系统信息处理流程,保证校园失物招领系统信息数据的安全,它是一个非常可靠,非常安全的应用程序。 ,管理员权限操作的功能包括管理公告,管理校园失物招领系统信息,包括失物招领管理,培训管理,寻物启事管理,薪资管理等,可以管理公告。 失物招领管理界面,管理员在失物招领管理界面中可以对界面中显示,可以对失物招领信息的失物招领状态进行查看,可以添加新的失物招领信息等。寻物启事管理界面,管理员在寻物启事管理界面中查看寻物启事种类信息,寻物启事描述信息,新增寻物启事信息等。公告管理界面,管理员在公告管理界面中新增公告,可以删除公告。公告类型管理界面,管理员在公告类型管理界面查看公告的工作状态,可以对公告的数据进行导出,可以添加新公告的信息,可以编辑公告信息,删除公告信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值