一般情況,查詢中需要有復合索引的前導列,才會使用復合索引
3.1)INDEX SKIP SCAN(復合索引之索引跳躍掃描)
Oracle 9i后提供,有時候復合索引的前導列(索引包含的第一列)沒有在查詢語句中出現,oralce也會使用該復合索引,
這時候就使用的INDEX SKIP SCAN;
3.2)什么時候會觸發 INDEX SKIP SCAN
前提條件:表有一個復合索引,且在查詢時有除了前導列(索引中第一列)外的其他列作為條件,並且優化器模式為CBO時當Oracle發現前導列的唯一值個數很少時,會將每個唯一值都作為常規掃描的入口,在此基礎上做一次查找,最后合並這些查詢;
例如:
假設表emp有ename(雇員名稱)、job(職位名)、sex(性別)三個字段,並且建立了如 create index idx_emp on emp (sex, ename, job) 的復合索引;因為性別只有 '男' 和 '女' 兩個值,所以為了提高索引的利用率,Oracle可將這個復合索引拆成 ('男', ename, job),('女', ename, job)這兩個復合索引;當查詢 select * from emp where job = 'Programmer' 時該查詢發出后: Oracle先進入sex為'男'的入口,這時候使用到了 ('男', ename, job) 這條復合索引,查找 job = 'Programmer' 的條目;再進入sex為'女'的入口,這時候使用到了 ('女', ename, job) 這條復合索引,查找 job = 'Programmer' 的條目;最后合並查詢到的來自兩個入口的結果集。
不走索引的原因,大概有如下8種:
1)建立組合索引,但查詢謂詞並未使用組合索引的第一列,此處有一個INDEX SKIP SCAN概念。
2)在包含有null值的table列上建立索引,當時使用select count(*) from table時不會使用索引。
3)在索引列上使用函數時不會使用索引,如果一定要使用索引只能建立函數索引。
如:Where條件中對字段增加處理函數將不使用該列的索引
select * from emp where to_char(hire_date,'yyyymmdd')='20080411' (不使用)
select * from emp where hire_date = to_char('20080411','yyyymmdd') (使用)
4)當被索引的列進行隱式的類型轉換時不會使用索引。
示例1:
select * from t where indexed_column = 5,而indexed_column列建立索引但類型是字符型,這時Oracle會產生隱式的類型轉換,轉換后的語句類似於select * from t where to_number(indexed_column) = 5,此時不走索引的情況類似於case3
示例2:日期轉換也有類似問題
select * from t where trunc(date_col) = trunc(sysdate)其中date_col為索引列,這樣寫不會走索引,可改寫成select * from t where date_col >= trunc(sysdate) and date_col < trunc(sysdate+1),此查詢會走索引。
5)並不是所有情況使用索引都會加快查詢速度,full scan table 有時會更快,尤其是當查詢的數據量占整個表的比重較大時,因為full scan table采用的是多塊讀,
當Oracle優化器沒有選擇使用索引時不要立即強制使用,要充分證明使用索引確實查詢更快時再使用強制索引。
6)<>
7)like’%dd’百分號在前
8)not in ,not exist
