高效的SQL【Composite Indexes(最佳前导列的选择)】

Composite Indexes(最佳前导列的选择)

 

一、前导列是否有序对composite indexes的影响大

 

1、创建表t1(x,y)  x有序列,y随意列

doudou@TEST> begin

  2  for i in 1.. 1000000 loop

  3  insert into t1 values (i,to_char(dbms_random.random,'999999999999') );

  4  if mod(i,100000)=0

  5  then

  6  commit;

  7  end if;

  8  end loop;

  9  end;

 10  /

 

PL/SQL procedure successfully completed.

 

2、组合索引:前导列是否有序的列对clustering_factor影响大。

doudou@TEST> create index idx_t1_01 on t1(x,y) ;

 

Index created.

 

doudou@TEST> create index idx_t1_02 on t1(y,x);

 

Index created.

 

doudou@TEST> select index_name,table_name,clustering_factor from user_indexes where table_name='T1';

 

INDEX_NAME                     TABLE_NAME                     CLUSTERING_FACTOR

------------------------------ ------------------------------ -----------------

IDX_T1_02                      T1                                        999562

IDX_T1_01                      T1                                          2402

 

doudou@TEST> drop index idx_t1_02;

 

Index dropped.

 

3、数据相同的2个表,不同前导列的组合索引,查看效率

 

doudou@TEST> create table t2 as select * from t1;

 

Table created.

 

doudou@TEST> create index idx_t2_01 on t2(y,x);

 

Index created.

 

doudou@TEST> select index_name,table_name,clustering_factor from user_indexes where table_name='T2';

 

INDEX_NAME                     TABLE_NAME                     CLUSTERING_FACTOR

------------------------------ ------------------------------ -----------------

IDX_T2_01                      T2                                        999591

 

doudou@TEST> select index_name,table_name,clustering_factor from user_indexes where table_name='T1';

 

INDEX_NAME                     TABLE_NAME                     CLUSTERING_FACTOR

------------------------------ ------------------------------ -----------------

IDX_T1_01                      T1                                          2402

 

sys@TEST> alter system flush shared_pool; --(生产库慎用,会造成大量物理读)

 

System altered.

 

doudou@TEST> exec dbms_stats.gather_table_stats('DOUDOU','T1',cascade=>true); --cascade=>true收集统计索引信息,默认为flase

 

PL/SQL procedure successfully completed.

 

doudou@TEST> exec dbms_stats.gather_table_stats('DOUDOU','T2',cascade=>true);

 

PL/SQL procedure successfully completed.

 

3-1、等值查询

 

doudou@TEST> select count(*) from t1 where x=1 and y=-1481404810;

 

  COUNT(*)

----------

         1

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1645197104

 

-------------------------------------------------------------------------------

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |           |     1 |    12 |     3   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE   |           |     1 |    12 |            |          |

|*  2 |   INDEX RANGE SCAN| IDX_T1_01 |     1 |    12 |     3   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("X"=1 AND "Y"=(-1481404810))

 

 

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

          3  consistent gets

          0  physical reads

          0  redo size

        411  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

doudou@TEST> select count(*) from t2  where x=1 and y=-1481404810;

 

  COUNT(*)

----------

         1

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3050965404

 

-------------------------------------------------------------------------------

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |           |     1 |    12 |     3   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE   |           |     1 |    12 |            |          |

|*  2 |   INDEX RANGE SCAN| IDX_T2_01 |     1 |    12 |     3   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("Y"=(-1481404810) AND "X"=1)

 

 

Statistics

----------------------------------------------------------

          1  recursive calls

          0  db block gets

          3  consistent gets

          0  physical reads

          0  redo size

        411  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

clustering_factor高低,对index rang scan 模式。等值查询影响不大。】

 

3-2where 谓语使用“<>

 

doudou@TEST> select count(*) from t1  where x<10 and y>0;

 

  COUNT(*)

----------

         4

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 1645197104

 

-------------------------------------------------------------------------------

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |           |     1 |    12 |     3   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE   |           |     1 |    12 |            |          |

|*  2 |   INDEX RANGE SCAN| IDX_T1_01 |     1 |    12 |     3   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("Y">0 AND "X"<10)

       filter("Y">0)

 

 

Statistics

----------------------------------------------------------

          1  recursive calls

          0  db block gets

          3  consistent gets

          0  physical reads

          0  redo size

        411  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

doudou@TEST> select count(*) from t2 where x<10 and y>0;

 

  COUNT(*)

----------

         4

 

Execution Plan

----------------------------------------------------------

Plan hash value: 3321871023

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    12 |   542   (1)| 00:00:07 |

|   1 |  SORT AGGREGATE    |      |     1 |    12 |            |          |

|*  2 |   TABLE ACCESS FULL| T2   |     1 |    12 |   542   (1)| 00:00:07 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("X"<10 AND "Y">0)

 

 

Statistics

----------------------------------------------------------

          0  recursive calls

          0  db block gets

       2417  consistent gets

          0  physical reads

          0  redo size

        411  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

clustering_factor高低,对index rang scan 模式。where 谓语使用“<>”,clustering_factor对索引影响大】

 

二、前导列选择度高低对composite indexes的影响小

 

1t3,t4数据相同  x列选择度高,y列选择低

 

doudou@TEST> create index idx_t3_01 on t3(x,y);

 

Index created.

 

doudou@TEST> create index idx_t4_01 on t4(y,x);

 

Index created.

 

doudou@TEST> select index_name,table_name,clustering_factor from user_indexes where table_name='T3';

 

INDEX_NAME                     TABLE_NAME                     CLUSTERING_FACTOR

------------------------------ ------------------------------ -----------------

IDX_T3_01                      T3                                        995325

 

doudou@TEST> select index_name,table_name,clustering_factor from user_indexes where table_name='T4';

 

INDEX_NAME                     TABLE_NAME                     CLUSTERING_FACTOR

------------------------------ ------------------------------ -----------------

IDX_T4_01                      T4                                        999539

composite indexes clustering_factor差别小】

 

doudou@TEST> select count(*) from t3 where x=1 and y=765571731;

 

  COUNT(*)

----------

         1

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 30972477

 

-------------------------------------------------------------------------------

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |           |     1 |    26 |     3   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE   |           |     1 |    26 |            |          |

|*  2 |   INDEX RANGE SCAN| IDX_T3_01 |     1 |    26 |     3   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("X"=1 AND "Y"=765571731)

 

Note

-----

   - dynamic sampling used for this statement

 

 

Statistics

----------------------------------------------------------

          9  recursive calls

          0  db block gets

         67  consistent gets

          0  physical reads

          0  redo size

        411  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

doudou@TEST> select count(*) from t4 where x=1 and y=765571731;

 

  COUNT(*)

----------

         1

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 2556691066

 

-------------------------------------------------------------------------------

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |           |     1 |    26 |     3   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE   |           |     1 |    26 |            |          |

|*  2 |   INDEX RANGE SCAN| IDX_T4_01 |     1 |    26 |     3   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("Y"=765571731 AND "X"=1)

 

Note

-----

   - dynamic sampling used for this statement

 

 

Statistics

----------------------------------------------------------

          9  recursive calls

          0  db block gets

         76  consistent gets

          2  physical reads

          0  redo size

        411  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

doudou@TEST> select count(*) from t3 where x=1 and  y>0;

 

  COUNT(*)

----------

     50037

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 30972477

 

-------------------------------------------------------------------------------

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |           |     1 |    26 |    58   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE   |           |     1 |    26 |            |          |

|*  2 |   INDEX RANGE SCAN| IDX_T3_01 | 15446 |   392K|    58   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("X"=1 AND "Y">0 AND "Y" IS NOT NULL)

 

Note

-----

   - dynamic sampling used for this statement

 

 

Statistics

----------------------------------------------------------

          9  recursive calls

          0  db block gets

        220  consistent gets

        148  physical reads

          0  redo size

        413  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

doudou@TEST>  select count(*) from t4 where x=1 and y>0;

 

  COUNT(*)

----------

     50037

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 405148644

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    26 |   481   (1)| 00:00:06 |

|   1 |  SORT AGGREGATE    |      |     1 |    26 |            |          |

|*  2 |   TABLE ACCESS FULL| T4   | 34100 |   865K|   481   (1)| 00:00:06 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("X"=1 AND "Y">0)

 

Note

-----

   - dynamic sampling used for this statement

 

 

Statistics

----------------------------------------------------------

         28  recursive calls

          0  db block gets

       2215  consistent gets

          0  physical reads

          0  redo size

        413  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

         

         

doudou@TEST> select count(*) from t3 where y=765571731;

 

  COUNT(*)

----------

         1

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 463314188

 

---------------------------------------------------------------------------

| Id  | Operation          | Name | Rows  | Bytes | Cost (%CPU)| Time     |

---------------------------------------------------------------------------

|   0 | SELECT STATEMENT   |      |     1 |    13 |   470   (1)| 00:00:06 |

|   1 |  SORT AGGREGATE    |      |     1 |    13 |            |          |

|*  2 |   TABLE ACCESS FULL| T3   |    23 |   299 |   470   (1)| 00:00:06 |

---------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - filter("Y"=765571731)

 

Note

-----

   - dynamic sampling used for this statement

 

 

Statistics

----------------------------------------------------------

          5  recursive calls

          0  db block gets

       2201  consistent gets

          0  physical reads

          0  redo size

        411  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

          1  rows processed

 

doudou@TEST> select count(*) from t4 where y=765571731;

 

  COUNT(*)

----------

         1

 

 

Execution Plan

----------------------------------------------------------

Plan hash value: 2556691066

 

-------------------------------------------------------------------------------

| Id  | Operation         | Name      | Rows  | Bytes | Cost (%CPU)| Time     |

-------------------------------------------------------------------------------

|   0 | SELECT STATEMENT  |           |     1 |    13 |     3   (0)| 00:00:01 |

|   1 |  SORT AGGREGATE   |           |     1 |    13 |            |          |

|*  2 |   INDEX RANGE SCAN| IDX_T4_01 |     1 |    13 |     3   (0)| 00:00:01 |

-------------------------------------------------------------------------------

 

Predicate Information (identified by operation id):

---------------------------------------------------

 

   2 - access("Y"=765571731)

 

Note

-----

   - dynamic sampling used for this statement

 

 

Statistics

----------------------------------------------------------

          9  recursive calls

          0  db block gets

         76  consistent gets

          0  physical reads

          0  redo size

        411  bytes sent via SQL*Net to client

        400  bytes received via SQL*Net from client

          2  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

1         rows processed

【选择度高低对composite indexes影响很小】

 

 

总结:

1、  前导列是否有序对clustering_factor影响大。前导列有序的composite indexes clustering_factor 低(性能高)。【反之则性能低】

2、  前导列选择度高低对clustering_factor影响小。进而对composite indexes影响小。

3、  Clustering_factor高低对 index range scan : 等值查询影响小< and >影响大。

 

建议:

         Composite indexes 前导列最好是有序的,这样clustering_factor低,性能会高。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值