索引跳躍式掃描(INDEX SKIP SCAN)適用於全部類型的複合B樹索引(包括惟一性索引和非惟一性索引),它使那些在where條件中沒有對目標索引的前導列指定查詢條件但同時又對該 索引的非前導列指定了查詢條件的目標SQL依然能夠用上該索引,這就像是在掃描該索引時跳過了它的前導列,直接從該索引的非前導列開始掃描同樣(實際的執行過程並不是如此),這也是索引跳躍式掃描中"跳躍"(SKIP)一詞的含義。sql
爲何在where條件中沒有對目標索引的前導列指定查詢條件但Oracle依然能夠用上該索引呢?這是由於Oracle幫你對該索引的前導列的全部distinct值作了遍歷。oop
建立一個測試表EMPLOYEE:測試
create table employee(gender varchar2(1),employee_id number);
將該表的列EMPLOYEE_ID的屬性設爲NOT NULL:spa
alter table employee modify(employee_id not null);
建立一個名爲IDX_EMPOLYEE的複合B樹索引,其中列GENDER是該索引的前導列,列EMPLOYEE_ID是該索引的第二列:code
create index idx_employee on employee(gender,employee_id);
使用以下PL/SQL代碼往表EMPLOYEE中插入10,000條記錄,其中5,000條記錄的列GENDER的值爲"F",另外5,000條記錄的列GENDER的值爲"M":htm
begin for i in 1..5000 loop insert into employee values ('F',i); end loop; commit; end; begin for i in 5001..10000 loop insert into employee values ('M',i); end loop; commit; end;
analyze table EMPLOYEE compute statistics for table for all columns for all indexes;
執行如下sqlblog
select * from employee where employee_id = 100;
where條件是"employee_id = 100",即它只對複合B樹索引IDX_EMPOLYEE的第二列EMPLOYEE_ID指定了查詢條件,但並無對該索引的前導列GENDER指定任何查詢條件。索引
set autotrace traceonly select * from employee where employee_id = 100;
執行計劃以下:ip
從上述顯示內容能夠看出,Oracle在執行時用上了索引IDX_EMPOLYEE,而且其執行計劃走的就是對該索引的索引跳躍式掃描。get
這裏在沒有指定前導列的狀況下還能用上述索引,就是由於Oracle幫咱們對該索引的前導列的全部distinct值作了遍歷。
所謂的對目標索引的全部distinct值作遍歷,其實際含義至關於對原目標SQL作等價改寫(即把要用的目標索引的全部前導列的distinct 值都加進來)。索引IDX_EMPOLYEE的前導列GENDER的distinct值只有"F"和"M"兩個值,因此這裏能使用索引 IDX_EMPOLYEE的緣由能夠簡單地理解成是Oracle將範例SQL 9等價改寫成了以下形式:
select * from employee where gender = 'F' and employee_id = 100 union all select * from employee where gender = 'M' and employee_id = 100;
Oracle中的索引跳躍式掃描僅僅適用於那些目標索引前導列的distinct值數量較少、後續非前導列的可選擇性又很是好的情形,由於索引跳躍式掃描的執行效率必定會隨着目標索引前導列的distinct值數量的遞增而遞減。