第三講、索引再好,不用也是白搭
拋開前面所說的,假設你設置了一個非常好的索引,任何傻瓜都知道應該使用它,但是Oracle卻偏偏不用,那麼,需要做的第一件事情,是審視你的sql語句。
Oracle要使用一個索引,有一些最基本的條件:
1 ,where 子句中的這個字段,必須是復合索引的第一個字段;
2 ,where 子句中的這個字段,不應該參與任何形式的計算
具體來講,假設一個索引是按f1, f2, f3的次序建立的,現在有一個sql 語句 , where 子句是f2 = : var2, 則因為f2不是索引的第1個字段,無法使用該索引。
第2個問題,則在我們之中非常嚴重。以下是從實際系統上面抓到的幾個例子:
Select jobid from mytabs where isReq='0' and to_date (updatedate) >= to_Date ( '2001-7-18', 'YYYY-MM-DD')
以上的例子能很容易地進行改進。請注意這樣的語句每天都在我們的系統中運行,消耗我們有限的cpu和內存資源。
除了1 ,2 這兩個我們必須牢記於心的原則外,還應盡量熟悉各種操作符對Oracle 是否使用索引的影響。這裡我只講哪些操作或者操作符會顯式(explicitly)地阻止Oracle 使用索引。以下是一些基本規則:
1 ,如果f1和f2是同一個表的兩個字段,則f1>f2, f1>=f2, f1
2 ,f1 is null, f1 is not null, f1 not in, f1 !=, f1 like ‘ %pattern% ' ;
3 ,Not exist
4 ,某些情況下,f1 in也會不用索引;
對於這些操作,別無辦法,只有盡量避免。比如,如果發現你的sql中的in操作沒有使用索引,也許可以將in操作改成 比較操作+ union all 。筆者在實踐中發現很多時候這很有效。
但是,Oracle 是否真正使用索引,使用索引是否真正有效,還是必須進行實地的測驗。合理的做法是,對所寫的復雜的sql, 在將它寫入應用程序之前,先在產品數據庫上做一次explain . explain 會獲得Oracle 對該ql 的解析( plan ) , 可以明確地看到Oracle 是如何優化該sql 的。
如果經常做explain, 就會發現,喜愛寫復雜的sql 並不是個好習慣,因為過分復雜的sql 其解析計劃往往不盡如人意。事實上,將復雜的sql 拆開,有時候會極大地提高效率,因為能獲得很好的優化。當然這已經是題外話了。