INDEX SKIP SCAN:跳躍式索引可以經過使用非前綴列提升索引的查詢性能.一般狀況下,掃描索引塊比掃描表數據塊快.
跳躍式索引可以使複合索引邏輯上拆分分一個個小的子索引.在跳躍式掃描中,複合索引的首列不會被限定在查詢中,由於它是跳躍式的.
數據庫肯定了必定數量的邏輯子索引經過在首列的去重的值中.當數據庫中複合索引的前導列有不多的去重的值和索引中有非前導列有不少重複的值時跳躍式掃描就會有不少優勢.
當複合索引的前導列沒有被查詢謂詞界定時,數據庫會選擇跳躍式索引.web
INDEX FULL SCAN:索引全掃描會排除排序操做,由於數據已經被按索引鍵值排序.讀數據塊是逐個讀的.數據庫在以下任何一個狀況時可能會使用full scan:
An ORDER BY clause that meets the following requirements is present in the query(有order by子句存在於查詢中):
All of the columns in the ORDER BY clause must be in the index.(在order by中的全部列必須被索引)
The order of the columns in the ORDER BY clause must match the order of the leading index columns.(在order by子句中排序的列必須匹配排序的前導列)
The ORDER BY clause can contain all of the columns in the index or a subset of the columns in the index.(order by子句中包含在索引中的全部列或者索引列的一個子集)
數據庫
舉例:緩存
SESSION1:
SQL> create table emp5 as select * from emp;
Table created.
SQL> create index skip1 on emp5(job,empno);
Index created.
SQL> commit;
Commit complete.
SQL> set autotrace traceon exp stat;
SQL> select count(*) from emp5 where empno=7900;
Execution Plan
----------------------------------------------------------
Plan hash value: 853491148
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
|* 2 | INDEX FULL SCAN| SKIP1 | 1 | 13 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPNO"=7900)
filter("EMPNO"=7900)
Note
-----
- dynamic sampling used for this statement (level=2) -------此處爲動態信息採集,由於表沒有被分析.
Statistics
----------------------------------------------------------
5 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
526 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)
1 rows processed
----------能夠看出新建表在沒有被分析的狀況下,默認是走INDEX FULL SCAN.
----------此時再開一個session2,執行以下的查詢:
SESSION2:
SQL> set autotrace traceon exp stat;
SQL> set serveroutput on
SQL> select /*+ index_ss(emp5 skip1) */ count(*) from emp5 where empno=7900;-----此處加hint強制走index skip scan,和上面的index full scan造成對比
Execution Plan
----------------------------------------------------------
Plan hash value: 3156092949
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
|* 2 | INDEX SKIP SCAN| SKIP1 | 1 | 13 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPNO"=7900)
filter("EMPNO"=7900)
Note
-----
- dynamic sampling used for this statement (level=2) -----由於表沒有被分析,索引此處也是動態信息採集
Statistics
----------------------------------------------------------
4 recursive calls
0 db block gets
6 consistent gets
0 physical reads
0 redo size
526 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)
1 rows processed
-------此時看不出具體的區別,由於表很小,而且已經被緩存到SGA中.在session2中再執行如下操做:
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL> select /*+ index_ss(emp5 skip1) */ count(*) from emp5 where empno=7900;
Execution Plan
----------------------------------------------------------
Plan hash value: 3156092949
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
|* 2 | INDEX SKIP SCAN| SKIP1 | 1 | 13 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPNO"=7900)
filter("EMPNO"=7900)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
62 recursive calls
0 db block gets
56 consistent gets
15 physical reads
0 redo size
526 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
1 rows processed
-------在SESSION1也執行如下操做,確保不受緩存的影響:
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL> select count(*) from emp5 where empno=7900;
Execution Plan
----------------------------------------------------------
Plan hash value: 853491148
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 13 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 13 | | |
|* 2 | INDEX FULL SCAN| SKIP1 | 1 | 13 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPNO"=7900)
filter("EMPNO"=7900)
Note
-----
- dynamic sampling used for this statement (level=2)
Statistics
----------------------------------------------------------
62 recursive calls
0 db block gets
56 consistent gets
17 physical reads ----------------此時能夠看出微小的區別,即跳躍式索引產生的物理讀比索引全掃描產生的物理讀小.
0 redo size
526 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
1 rows processed
----------在SESSION1中分析這個表,再次看分析後的執行計劃:
SQL> analyze table emp5 compute statistics;
Table analyzed.
SQL> alter system flush shared_pool;
System altered.
SQL> alter system flush buffer_cache;
System altered.
SQL> select count(*) from emp5 where empno=7900;
Execution Plan
----------------------------------------------------------
Plan hash value: 3156092949
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | INDEX SKIP SCAN| SKIP1 | 1 | 3 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPNO"=7900)
filter("EMPNO"=7900)
Statistics
----------------------------------------------------------
27 recursive calls
0 db block gets
50 consistent gets
15 physical reads
0 redo size
526 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
1 rows processed
-------------可見分析事後,對於複合索引SKIP1,前導列沒有在where的條件下的狀況,數據庫會自動選擇INDEX SKIP SCAN.
-------------在SESSION2中,執行如下操做,看具體區別:
SQL> alter system flush buffer_cache;
System altered.
SQL> alter system flush shared_pool;
System altered.
SQL> select /*+ index_ss(emp5 skip1) */ count(*) from emp5 where empno=7900;
Execution Plan
----------------------------------------------------------
Plan hash value: 3156092949
--------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
--------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 3 | 1 (0)| 00:00:01 |
| 1 | SORT AGGREGATE | | 1 | 3 | | |
|* 2 | INDEX SKIP SCAN| SKIP1 | 1 | 3 | 1 (0)| 00:00:01 |
--------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("EMPNO"=7900)
filter("EMPNO"=7900)
Statistics
----------------------------------------------------------
27 recursive calls
0 db block gets
50 consistent gets
11 physical reads -------------------此處少了一些,應該是緩存的遊標或者在LRU的熱端,致使少了一些物理讀
0 redo size
526 bytes sent via SQL*Net to client
523 bytes received via SQL*Net from client
2 SQL*Net roundtrips to/from client
6 sorts (memory)
0 sorts (disk)
1 rows processed
總結:最好把表分析事後,刷新緩存,這樣作實驗纔有意義.若是走動態採樣,能夠執行hint看區別.
索引跳躍式掃描能夠容許優化器使用組合索引,即使索引的前導列沒有出如今WHERE子句中。索引跳躍式掃描比全索引掃描要快的多session