组合索引(concatenated index):由多个列构成的索引,
创建组合索引create index idx_detp on detp(col1,col2,col3,....),则我们称idx_emp索引为组合索引。
在组合索引中有一个重要的概念:引导列(leading column),在上面的例子中,col1列为引导列。
当我们进行查询时where 限制条件必须有引导列.
create index idx_detp on detp(col1,col2,col3,....) 在idx_detp组合索引,col1为引导列
上面的例子,
一,使用组合索引的情况(where 条件中有引导列)
1,where col1 =
2,,where col1 = and col2=
3,,where col2 = and col1=
二,不会使用该索引(where 条件中没有引导列)
where col2= ”查询就不会使用该索引。
所以限制条件中包含先导列时,该限制条件才会使用该组合索引。
下面是测试案例
一,以为dba_objects表的数据来测试,建一个测试表
SQL> create table t as select * from dba_objects;
Table created.
SQL> select count(*) from t;
COUNT(*)
----------
72766
二,创建组合索引object_id列为引导列
Index created.
SQL> show parameter sql_trace;
NAME TYPE VALUE
--------- ------------ ------------------
sql_trace boolean FALSE
SQL> alter system set sql_trace=true;
System altered.
SQL> set autotrace traceonly;
SQL> select * from t where object_id=20; --------从执行计划可以看出,走的是索引
Execution Plan
----------------------------------------------------------
Plan hash value: 46312585
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 207 | 3 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | OBJECT_ID_T | 1 | | 2 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=20)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
7 recursive calls
0 db block gets
71 consistent gets
0 physical reads
0 redo size
1389 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
SQL> select * from t where data_object_id=2; --- data_object_id不是引导了,在查找中因为where条件,没有引导列,虽然建了索引,但是没有起到作用
18 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 11 | 2277 | 283 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 11 | 2277 | 283 (1)| 00:00:04 | ----------走的是全表索引
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DATA_OBJECT_ID"=2)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
4 recursive calls
0 db block gets
1104 consistent gets
1035 physical reads
0 redo size
2065 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
18 rows processed
SQL> select * from t where data_object_id=2 and object_id=20; -------where条件有引导列,在查询中,执行计划走的是组合索引
Execution Plan
----------------------------------------------------------
Plan hash value: 46312585
-------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 207 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| T | 1 | 207 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | OBJECT_ID_T | 1 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("OBJECT_ID"=20 AND "DATA_OBJECT_ID"=2)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
9 recursive calls
0 db block gets
71 consistent gets
0 physical reads
0 redo size
1389 bytes sent via SQL*Net to client
419 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
1 rows processed
---------------------------------------------------------------
在组合索引中使用不等于操作符(<>、!=) 不走索引,
测试案例,
SQL> select * from t where data_object_id=2 and object_id<>20; --------没有走索引
17 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 33 | 6831 | 283 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 33 | 6831 | 283 (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DATA_OBJECT_ID"=2 AND "OBJECT_ID"<>20)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
4 recursive calls
0 db block gets
1104 consistent gets
1035 physical reads
0 redo size
2042 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
17 rows processed
SQL> select * from t where data_object_id=2 and object_id !=20; ----使用了!=不等符,没有走索引
17 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 1601196873
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 33 | 6831 | 283 (1)| 00:00:04 |
|* 1 | TABLE ACCESS FULL| T | 33 | 6831 | 283 (1)| 00:00:04 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
1 - filter("DATA_OBJECT_ID"=2 AND "OBJECT_ID"<>20)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
4 recursive calls
0 db block gets
1104 consistent gets
1035 physical reads
0 redo size
2042 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
17 rows processed
修改sql语句,使它走组合索引(通过把不等于操作符改成OR条件,就可以使用索引,以避免全表扫描)
SQL> select * from t where data_object_id=2 and (object_id <20 or object_id>20);
17 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 396627435
--------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 65 | 13455 | 8 (0)| 00:00:01 |
| 1 | CONCATENATION | | | || |
| 2 | TABLE ACCESS BY INDEX ROWID| T | 33 | 6831 | 4 (0)| 00:00:01 |
|* 3 | INDEX RANGE SCAN | OBJECT_ID_T | 3 | | 3 (0)| 00:00:01 |
| 4 | TABLE ACCESS BY INDEX ROWID| T | 32 | 6624 | 4 (0)| 00:00:01 |
|* 5 | INDEX RANGE SCAN | OBJECT_ID_T | 3 | | 3 (0)| 00:00:01 |
--------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
3 - access("OBJECT_ID">20 AND "DATA_OBJECT_ID"=2 AND "OBJECT_ID" IS NOT NULL)
filter("DATA_OBJECT_ID"=2)
5 - access("DATA_OBJECT_ID"=2 AND "OBJECT_ID"<20)
filter("DATA_OBJECT_ID"=2 AND LNNVL("OBJECT_ID">20))
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
13 recursive calls
0 db block gets
446 consistent gets
0 physical reads
0 redo size
2086 bytes sent via SQL*Net to client
430 bytes received via SQL*Net from client
3 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
17 rows processed