索引(二):储键值、有序、高度相关案例。

索引的特性存储键值、有序、高度相关案例。

1、‘分区表各类聚合优化玄机

drop table range_part_tab purge;
--注意,此分区为范围分区

--例子1
create table range_part_tab (id number,deal_date date,area_code number,nbr number,contents varchar2(4000))
           partition by range (deal_date)
           (
           partition p_201301 values less than (TO_DATE('2013-02-01', 'YYYY-MM-DD')),
           partition p_201302 values less than (TO_DATE('2013-03-01', 'YYYY-MM-DD')),
           partition p_201303 values less than (TO_DATE('2013-04-01', 'YYYY-MM-DD')),
           partition p_201304 values less than (TO_DATE('2013-05-01', 'YYYY-MM-DD')),
           partition p_201305 values less than (TO_DATE('2013-06-01', 'YYYY-MM-DD')),
           partition p_201306 values less than (TO_DATE('2013-07-01', 'YYYY-MM-DD')),
           partition p_201307 values less than (TO_DATE('2013-08-01', 'YYYY-MM-DD')),
           partition p_201308 values less than (TO_DATE('2013-09-01', 'YYYY-MM-DD')),
           partition p_201309 values less than (TO_DATE('2013-10-01', 'YYYY-MM-DD')),
           partition p_201310 values less than (TO_DATE('2013-11-01', 'YYYY-MM-DD')),
           partition p_201311 values less than (TO_DATE('2013-12-01', 'YYYY-MM-DD')),
           partition p_201312 values less than (TO_DATE('2014-01-01', 'YYYY-MM-DD')),
           partition p_201401 values less than (TO_DATE('2014-02-01', 'YYYY-MM-DD')),
           partition p_201402 values less than (TO_DATE('2014-03-01', 'YYYY-MM-DD')),
           partition p_max values less than (maxvalue)
           )
           ;

alter table RANGE_PART_TAB modify nbr not null;
--以下是插入2020年一整年日期随机数和表示xx地区号含义(591到599)的随机数记录,共有10万条,如下:
insert into range_part_tab (id,deal_date,area_code,nbr,contents)
      select rownum,
             to_date( to_char(sysdate-365,'J')+TRUNC(DBMS_RANDOM.VALUE(0,365)),'J'),
             ceil(dbms_random.value(591,599)),
             ceil(dbms_random.value(18900000001,18999999999)),
             rpad('*',400,'*')
        from dual
      connect by rownum <= 100000;
commit;

 

--以下是插入2020年一整年日期随机数和表示福建地区号含义(591到599)的随机数记录,共有10万条,如下:
insert into range_part_tab (id,deal_date,area_code,nbr,contents)
      select rownum,
             to_date( to_char(sysdate,'J')+TRUNC(DBMS_RANDOM.VALUE(0,365)),'J'),
             ceil(dbms_random.value(591,599)),
             ceil(dbms_random.value(18900000001,18999999999)),
             rpad('*',400,'*')
        from dual
      connect by rownum <= 100000;
commit;

create index idx_part_id on range_part_tab (id) ;
create index idx_part_nbr on range_part_tab (nbr) local;

--统计信息系统一般会自动收集,这只是首次建成表后需要操作一下,以方便测试
exec dbms_stats.gather_table_stats(ownname => 'SCOTT',tabname => 'RANGE_PART_TAB',estimate_percent => 10,method_opt=> 'for all indexed columns',cascade=>TRUE) ;  


set autotrace on
set linesize 1000
select max(nbr) max_nbr from range_part_tab partition(p_201305);(使用分区的写法,使用了nbr的索引)

Execution Plan
----------------------------------------------------------
Plan hash value: 1219885076

------------------------------------------------------------------------------------------------------------
| Id  | Operation            | Name       | Rows  | Bytes | Cost (%CPU)| Time       | Pstart| Pstop |
------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT        |           |     1 |    13 |     1   (0)| 00:00:01 |       |       |
|   1 |  SORT AGGREGATE         |           |     1 |    13 |        |       |       |       |
|   2 |   PARTITION RANGE SINGLE    |           |     1 |    13 |     1   (0)| 00:00:01 |     5 |     5 |
|   3 |    INDEX FULL SCAN (MIN/MAX)| IDX_PART_NBR |     1 |    13 |     1   (0)| 00:00:01 |     5 |     5 |
------------------------------------------------------------------------------------------------------------


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

select max(nbr) max_nbr(经典查询方法走了全表扫描,而不走索引,因为有deal_date过滤条件上没有索引,假设走了索引那么它需要nbr索引的rowid回表去取 deal_data的数据)
  from range_part_tab
 where deal_date >= TO_DATE('2013-05-01', 'YYYY-MM-DD')
   and deal_date < TO_DATE('2013-06-01', 'YYYY-MM-DD');

Execution Plan
----------------------------------------------------------
Plan hash value: 4190023598

----------------------------------------------------------------------------------------------------------
| Id  | Operation        | Name         | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
----------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT    |         |     1 |    22 |     2   (0)| 00:00:01 |     |     |
|   1 |  SORT AGGREGATE     |         |     1 |    22 |          |      |     |     |
|   2 |   PARTITION RANGE SINGLE|         |     1 |    22 |     2   (0)| 00:00:01 |     5 |     5 |
|   3 |    TABLE ACCESS FULL    | RANGE_PART_TAB |     1 |    22 |     2   (0)| 00:00:01 |     5 |     5 |
----------------------------------------------------------------------------------------------------------


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

2、分区索引的性能反而更低

drop table part_tab purge;
create table part_tab (id int,col2 int,col3 int)
        partition by range (id)
        (
        partition p1 values less than (10000),
        partition p2 values less than (20000),
        partition p3 values less than (30000),
        partition p4 values less than (40000),
        partition p5 values less than (50000),
        partition p6 values less than (60000),
        partition p7 values less than (70000),
        partition p8 values less than (80000),
        partition p9 values less than (90000),
        partition p10 values less than (100000),
        partition p11 values less than (maxvalue)
        )
        ;
insert into part_tab select rownum,rownum+1,rownum+2 from dual connect by rownum <=110000;
commit;
create  index idx_par_tab_col2 on part_tab(col2) ;
create  index idx_par_tab_col3 on part_tab(col3) ;

drop table norm_tab purge;
create table norm_tab  (id int,col2 int,col3 int);
insert into norm_tab select rownum,rownum+1,rownum+2 from dual connect by rownum <=110000;
commit;
create  index idx_nor_tab_col2 on norm_tab(col2) ;
create  index idx_nor_tab_col3 on norm_tab(col3) ;

set autotrace traceonly
set linesize 1000
set timing on
select * from part_tab where col2=8 ;
执行计划
-----------------------------------------------------------------------------------------------------------------------
| Id  | Operation                          | Name             | Rows  | Bytes | Cost (%CPU)| Time     | Pstart| Pstop |
-----------------------------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT                   |                  |     1 |    39 |    13   (0)| 00:00:01 |       |       |
|   1 |  PARTITION RANGE ALL               |                  |     1 |    39 |    13   (0)| 00:00:01 |     1 |    11 |
|   2 |   TABLE ACCESS BY LOCAL INDEX ROWID| PART_TAB         |     1 |    39 |    13   (0)| 00:00:01 |     1 |    11 |
|*  3 |    INDEX RANGE SCAN                | IDX_PAR_TAB_COL2 |     1 |       |    12   (0)| 00:00:01 |     1 |    11 |
-----------------------------------------------------------------------------------------------------------------------
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
         24  consistent gets
          0  physical reads
          0  redo size
        539  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
          
          
select * from norm_tab where col2=8 ;

执行计划
------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name             | Rows  | Bytes | Cost (%CPU)| Time     |
------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                  |     1 |    39 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| NORM_TAB         |     1 |    39 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_NOR_TAB_COL2 |     1 |       |     1   (0)| 00:00:01 |
------------------------------------------------------------------------------------------------
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        543  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
        
        
        
          
select * from part_tab where col2=8 and id=2;
select * from norm_tab where col2=8 and id=2;

--查看索引高度等信息
select index_name,
          blevel,
          leaf_blocks,
          num_rows,
          distinct_keys,
          clustering_factor
     from user_ind_statistics
    where table_name in( 'NORM_TAB');
    
select index_name,
          blevel,
          leaf_blocks,
          num_rows,
          distinct_keys,
          clustering_factor FROM USER_IND_PARTITIONS where index_name like 'IDX_PAR_TAB%';

以上查询条件建立了本地索引,但是本地索引在查询条件中没有被用到,这样反而不如建立全局索引;以上还说明如果本都索引用不到的话,对分区表的查询反而不如普通表的索引查询效率要高。所以建立本地索引还是全局索引要考业务的需求来建立。

3、同时取最大值和最小值的优化案例

MAX/MIN 的索引优化
  drop table t purge;
  create table t as select * from dba_objects;
  update t set object_id=rownum;
  commit;
  alter table t add constraint pk_object_id primary key (OBJECT_ID);
  set autotrace on
  set linesize 1000
  select max(object_id) from t;
  select min(object_id) from t;

 
--等价改写,为数不多的SQL改写复杂了性能更优的情况
set linesize 1000
set autotrace on

select max(object_id),min(object_id) from t;
执行计划
--------------------------------------------------------------------------------------
| Id  | Operation             | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT      |              |     1 |    13 |    46   (0)| 00:00:01 |
|   1 |  SORT AGGREGATE       |              |     1 |    13 |            |          |
|   2 |   INDEX FAST FULL SCAN| PK_OBJECT_ID | 74796 |   949K|    46   (0)| 00:00:01 |
--------------------------------------------------------------------------------------
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
        160  consistent gets
          0  physical reads
          0  redo size
        502  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed
   
   
          
select max, min
  from (select max(object_id) max from t ) a,
       (select min(object_id) min from t ) b;
执行计划
---------------------------------------------------------------------------------------------
| Id  | Operation                    | Name         | Rows  | Bytes | Cost (%CPU)| Time     |
---------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |              |     1 |    26 |     4   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                |              |     1 |    26 |     4   (0)| 00:00:01 |
|   2 |   VIEW                       |              |     1 |    13 |     2   (0)| 00:00:01 |
|   3 |    SORT AGGREGATE            |              |     1 |    13 |            |          |
|   4 |     INDEX FULL SCAN (MIN/MAX)| PK_OBJECT_ID |     1 |    13 |     2   (0)| 00:00:01 |
|   5 |   VIEW                       |              |     1 |    13 |     2   (0)| 00:00:01 |
|   6 |    SORT AGGREGATE            |              |     1 |    13 |            |          |
|   7 |     INDEX FULL SCAN (MIN/MAX)| PK_OBJECT_ID |     1 |    13 |     2   (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
统计信息
----------------------------------------------------------
          0  recursive calls
          0  db block gets
          4  consistent gets
          0  physical reads
          0  redo size
        480  bytes sent via SQL*Net to client
        416  bytes received via SQL*Net from client
          2  SQL*Net roundtrips to/from client
          0  sorts (memory)
          0  sorts (disk)
          1  rows processed

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值