本文主要讨论以下几种索引访问方法:
1.索引唯一扫描(INDEX UNIQUE SCAN)
2.索引范围扫描(INDEX RANGE SCAN)
3.索引全扫描(INDEX FULL SCAN)
4.索引跳跃扫描(INDEX SKIP SCAN)
5.索引快速全扫描(INDEX FAST FULL SCAN)
索引唯一扫描(INDEX UNIQUE SCAN)
通过这种索引访问数据的特点是对于某个特定的值只返回一行数据,通常如果在查询谓语中使用UNIQE和PRIMARY KEY索引的列作为条件的时候会选用这种扫描;访问的高度总是索引的高度加一,除了某些特殊的情况,如另外存储的LOB对象。
SQL> set autotrace traceonly explain
SQL> select * from hr.employees where employee_id = 100;
Execution Plan
----------------------------------------------------------
Plan hash value: 1833546154
---------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
---------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 69 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 1 | 69 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | EMP_EMP_ID_PK | 1 | | 0 (0)| 00:00:01 |
---------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPLOYEE_ID"=100)
</div>
索引范围扫描(INDEX RANGE SCAN)
谓语中包含将会返回一定范围数据的条件时就会选用索引范围扫描,索引可以是唯一的亦可以是不唯一的;所指定的条件可以是(<,>,LIKE,BETWEEN,=)等运算符,不过使用LIKE的时候,如果使用了通配符%,极有可能就不会使用范围扫描,因为条件过于的宽泛了,下面是一个示例:
SQL> select * from hr.employees where DEPARTMENT_ID = 30;
6 rows selected.
Execution Plan
----------------------------------------------------------
Plan hash value: 2056577954
-------------------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
-------------------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 6 | 414 | 2 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES | 6 | 414 | 2 (0)| 00:00:01 |
|* 2 | INDEX RANGE SCAN | EMP_DEPARTMENT_IX | 6 | | 1 (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("DEPARTMENT_ID"=30)
Statistics
----------------------------------------------------------
8 recursive calls
0 db block gets
7 consistent gets
1 physical reads
0 redo size
1716 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
0 sorts (memory)
0 sorts (disk)
6 rows processed
</div>
范围扫描的条件需要准确的分析返回数据的数目,范围越大就越可能执行全表扫描;
SQL> select department_id,count(*) from hr.employees group by department_id order by count(*);
DEPARTMENT_ID COUNT(*)
------------- ----------
10 1
40 1
1
70 1
20 2
110 2
90 3
60 5
30 6
100 6
80 34
50 45
12 rows selected.
-- 这里使用数值最多的50来执行范围扫描
SQL> set autotrace traceonly explai