• 分页技术总结


    create table page as select * from dba_objects; 
    
    create index idx_page on page(object_id);
    create index idx_page_1 on page(owner,object_id);
    create index idx_page_2 on page(owner);
    create index idx_page_3 on page(object_id,owner);
    
    
    BEGIN
      DBMS_STATS.GATHER_TABLE_STATS(ownname          => 'SCOTT',
                                    tabname          => 'PAGE',
                                    estimate_percent => 100,
                                    method_opt       => 'for all columns size skewonly',
                                    no_invalidate    => FALSE,
                                    degree           => 4,
                                    cascade          => TRUE);
    END;
    
    
    select * from 
    (
    select * from 
    (
    select  a.*,rownum rn
      from page a 
     where object_id >1000 and owner='SYS'
     order by object_id desc
    ) where rownum<=20
    ) where rn>=0;
    
    
    
    分页语句必须要有order by ,order by 哪个列 哪个列必须有索引
    
    只要 分页有 sort order by  绝对是错的
    
    肯定没走索引
    
    
    SQL> select * from 
    (
    select * from 
    (
    select  a.*,rownum rn
      from page a 
     where object_id >1000 and owner='SYS'
     order by object_id desc
    ) where rownum<=20
    ) where rn>=0;  2    3    4    5    6    7    8    9   10  
    
    20 rows selected.
    
    
    Execution Plan
    ----------------------------------------------------------
    Plan hash value: 824209635
    
    -----------------------------------------------------------------------------------------
    | Id  | Operation		 | Name | Rows	| Bytes |TempSpc| Cost (%CPU)| Time	|
    -----------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT	 |	|    20 |  4400 |	|   910   (1)| 00:00:11 |
    |*  1 |  VIEW			 |	|    20 |  4400 |	|   910   (1)| 00:00:11 |
    |*  2 |   COUNT STOPKEY 	 |	|	|	|	|	     |		|
    |   3 |    VIEW 		 |	| 30424 |  6536K|	|   910   (1)| 00:00:11 |
    |*  4 |     SORT ORDER BY STOPKEY|	| 30424 |  2881K|  4000K|   910   (1)| 00:00:11 |
    |   5 |      COUNT		 |	|	|	|	|	     |		|
    |*  6 |       TABLE ACCESS FULL  | PAGE | 30424 |  2881K|	|   234   (1)| 00:00:03 |
    -----------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter("RN">=0)
       2 - filter(ROWNUM<=20)
       4 - filter(ROWNUM<=20)
       6 - filter("OWNER"='SYS' AND "OBJECT_ID">1000)
    
    
    Statistics
    ----------------------------------------------------------
           1153  recursive calls
    	  0  db block gets
           1336  consistent gets
           1036  physical reads
    	  0  redo size
           3175  bytes sent via SQL*Net to client
    	431  bytes received via SQL*Net from client
    	  3  SQL*Net roundtrips to/from client
    	 66  sorts (memory)
    	  0  sorts (disk)
    	 20  rows processed
    
    
    分页语句:
    1.必须有orderby 
    
    2.order by 哪个列,那个列就必须要有索引,利用索引已排序的特点。
    
    3.分页有 sort order by 重新对数据进行排序
    
    select * from 
    (
    select * from 
    (
    select  /*+ index(a) */  a.*,rownum rn
      from page a 
     where object_id >1000 and owner='SYS'
     order by object_id desc
    ) where rownum<=20
    ) where rn>=0; 
    
    
    SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
    
    PLAN_TABLE_OUTPUT
    -------------------------------------------------------------------------------------------------------------------
    
    -------------------------------------------------------------------------------------
    SQL_ID	4tub4ucyfwk79, child number 0
    -------------------------------------
    select * from ( select * from ( select	/*+ index(a) */  a.*,rownum rn
     from page a  where object_id >1000 and owner='SYS'  order by object_id
    desc ) where rownum<=20 ) where rn>=0
    
    Plan hash value: 4010810952
    
    -------------------------------------------------------------------------------------------------------------------
    
    -----------------
    | Id  | Operation			 | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers |  OMem |  
    
    1Mem | Used-Mem |
    -------------------------------------------------------------------------------------------------------------------
    
    -----------------
    |   0 | SELECT STATEMENT		 |	      |      1 |	|     20 |00:00:00.83 |     865 |	|	
    
    |	   |
    |*  1 |  VIEW				 |	      |      1 |     20 |     20 |00:00:00.83 |     865 |	|	
    
    |	   |
    |*  2 |   COUNT STOPKEY 		 |	      |      1 |	|     20 |00:00:00.83 |     865 |	|	
    
    |	   |
    |   3 |    VIEW 			 |	      |      1 |  30424 |     20 |00:00:00.83 |     865 |	|	
    
    |	   |
    |*  4 |     SORT ORDER BY STOPKEY	 |	      |      1 |  30424 |     20 |00:00:00.83 |     865 |  1824K|   
    
    650K| 1621K (0)|
    |   5 |      COUNT			 |	      |      1 |	|  29905 |00:00:00.65 |     865 |	|	
    
    |	   |
    |*  6 |       TABLE ACCESS BY INDEX ROWID| PAGE       |      1 |  30424 |  29905 |00:00:00.48 |     865 |	|	
    
    |	   |
    |*  7 |        INDEX RANGE SCAN 	 | IDX_PAGE_2 |      1 |  30835 |  30835 |00:00:00.10 |      66 |	|	
    
    |	   |
    -------------------------------------------------------------------------------------------------------------------
    
    -----------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter("RN">=0)
       2 - filter(ROWNUM<=20)
       4 - filter(ROWNUM<=20)
       6 - filter("OBJECT_ID">1000)
       7 - access("OWNER"='SYS')
    
    
    30 rows selected.
    
    
    SORT ORDER BY STOPKEY 也是错的
    
    
    select * from 
    (
    select * from 
    (
    select   /*+ index_desc(a idx_page_3) */    a.*,rownum rn
      from page a 
     where object_id >1000 and owner='SYS'
     order by object_id desc
    ) where rownum<=20
    ) where rn>=0; 
    
    SQL> select * from table(dbms_xplan.display_cursor(null,null,'ALLSTATS LAST'));
    
    PLAN_TABLE_OUTPUT
    -------------------------------------------------------------------------------------------------------------------
    
    -------------------------------------------------------------------------------------
    SQL_ID	8vy3s6f4nh4ga, child number 0
    -------------------------------------
    select * from ( select * from ( select	 /*+ index_desc(a idx_page_3)
    */    a.*,rownum rn   from page a  where object_id >1000 and
    owner='SYS'  order by object_id desc ) where rownum<=20 ) where rn>=0
    
    Plan hash value: 3526010999
    
    ------------------------------------------------------------------------------------------------------------------
    | Id  | Operation			 | Name       | Starts | E-Rows | A-Rows |   A-Time   | Buffers | Reads  |
    ------------------------------------------------------------------------------------------------------------------
    |   0 | SELECT STATEMENT		 |	      |      1 |	|     20 |00:00:00.01 |       9 |      2 |
    |*  1 |  VIEW				 |	      |      1 |     20 |     20 |00:00:00.01 |       9 |      2 |
    |*  2 |   COUNT STOPKEY 		 |	      |      1 |	|     20 |00:00:00.01 |       9 |      2 |
    |   3 |    VIEW 			 |	      |      1 |  30424 |     20 |00:00:00.01 |       9 |      2 |
    |   4 |     COUNT			 |	      |      1 |	|     20 |00:00:00.01 |       9 |      2 |
    |   5 |      TABLE ACCESS BY INDEX ROWID | PAGE       |      1 |  30424 |     20 |00:00:00.01 |       9 |      2 |
    |*  6 |       INDEX RANGE SCAN DESCENDING| IDX_PAGE_3 |      1 |  30424 |     20 |00:00:00.01 |       4 |      2 |
    ------------------------------------------------------------------------------------------------------------------
    
    Predicate Information (identified by operation id):
    ---------------------------------------------------
    
       1 - filter("RN">=0)
       2 - filter(ROWNUM<=20)
       6 - access("OBJECT_ID" IS NOT NULL AND "OBJECT_ID">1000 AND "OWNER"='SYS')
           filter("OWNER"='SYS')
    
    
    28 rows selected.
    
    
    多表关联后分页:
    
    select ... from a,b where a.id=b.id order by a.xx;
    
    a当驱动表 nl b
    
    分页SQL必须走NL循环 order by 谁 谁当驱动表
    
    1. 我们把它当成只 从a出数据
    
    
    2.值给a.xx建索引
    
    3.被驱动表 b b.id建索引 
    
    
    
    
    select ... from a,b where a.id=b.id order by a.xx,b.xxx;
    分页的 每页 取 20条
    
    这种SQL没法优化,order by 2个表没法优化
    
    
    select ... from a,b where a.id=b.id gropu by ...order by  分页的 每页 取 20条
    
    
    分页语句不能有group by ,distinct操作
    
    
    select ... from a left join b where ... order by b
    
    
    外链接 左链接 驱动表只能是a 那么order by a表
     
    
    
    select ... from a where 过滤条件 order by 另外一个列
    
    按where 条件列+order by 列创建索引
    
    
    
    select ... from a where owner='SB' and xx like '%jj%'  order by money
    
    这个时候建索引:money,owner,xx
    
    
    分页语句的优化技巧:
    
    1.分页SQL要想快最好走索引,根据order by asc/desc ,用hint index_asc/index_desc 
      强制它走索引INDEX FULL SCAN  DESCENDING/INDEX RANGE SCAN DESCENDING
    
    2.不要让Oracle扫描整个index,确保只扫描一部分索引块,然后回表就取得数据,然后
      就count stopkey
    
    3.一定要确保索引回表的时候不要在表上再去过滤,也就是说TABLE ACCESS BY INDEX ROWID
      上面没*,不然就可能扫描整个索引块,根据where条件可以创建组合索引
      (分区表要创建global index)
    
    4.看执行计划的时候不要被执行计划的基数给骗了----它可能显示是有误差的
    

  • 相关阅读:
    链路追踪
    Zuul网关
    MyBatis批量插入
    自定义组件使用v-model
    正则表达式入门
    博客园主题1【备份】
    关于我
    input输入框内容规范正则总结
    实例003:完全平方数
    python基础day5dict
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13352314.html
Copyright © 2020-2023  润新知