索引跳躍式掃描(INDEX SKIP SCAN)


索引跳躍式掃描(INDEX SKIP SCAN)

索引跳躍式掃描(INDEX SKIP SCAN)適用於所有類型的復合B樹索引(包括唯一性索引和非唯一性索引),它使那些在where條件中沒有對目標索引的前導列指定查詢條件但同時又對該 索引的非前導列指定了查詢條件的目標SQL依然可以用上該索引,這就像是在掃描該索引時跳過了它的前導列,直接從該索引的非前導列開始掃描一樣(實際的執行過程並非如此),這也是索引跳躍式掃描中"跳躍"(SKIP)一詞的含義。

為什么在where條件中沒有對目標索引的前導列指定查詢條件但Oracle依然可以用上該索引呢?這是因為Oracle幫你對該索引的前導列的所有distinct值做了遍歷。

實例。

創建一個測試表EMPLOYEE:

create table employee(gender varchar2(1),employee_id number);

將該表的列EMPLOYEE_ID的屬性設為NOT NULL:

alter table employee modify(employee_id not null);

創建一個名為IDX_EMPOLYEE的復合B樹索引,其中列GENDER是該索引的前導列,列EMPLOYEE_ID是該索引的第二列:

create index idx_employee on employee(gender,employee_id);

使用如下PL/SQL代碼往表EMPLOYEE中插入10,000條記錄,其中5,000條記錄的列GENDER的值為"F",另外5,000條記錄的列GENDER的值為"M":

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;
對表EMPLOYEE 及索引收集一下統計信息:

analyze table EMPLOYEE compute statistics for table for all columns for all indexes;

執行以下sql

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;

執行計划如下:

clip_image001

從上述顯示內容可以看出,Oracle在執行時用上了索引IDX_EMPOLYEE,並且其執行計划走的就是對該索引的索引跳躍式掃描。

這里在沒有指定前導列的情況下還能用上述索引,就是因為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值數量的遞增而遞減。

原文:

索引跳躍式掃描


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM