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-2 、 where 谓语使用“ < 和 > ”
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 的影响小
1 、 t3,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)
<!--[if !supportLists]--> 1 <!--[endif]--> 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 低,性能会高。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26442936/viewspace-751497/ ,如需转载,请注明出处,否则将追究法律责任。