where 用到的字段沒建立索引,就不走索引。 sql
下面這三種狀況也會走索引。 編程
where field1 like '%abc%' --like %
where substr(field1,1)='a' --函數
where field1 in ('a','b','c') --in oracle
索引列有函數處理或隱式轉換,不走索引 函數
索引列傾斜,個別值查詢時,走索引代價比走全表掃描高,因此不走索引 優化
索引列沒有限制 not null,索引不存儲空值,若是不限制索引列是not null,oracle會認爲索引列有可能存在空值,因此不會按照索引計算) spa
一、查詢謂詞沒有使用索引的主要邊界,可能會致使不走索引。好比,你查詢的是SELECT * FROM T WHERE Y=XXX;假如你的T表上有一個包含Y值的組合索引,可是優化器會認爲須要一行行的掃描會更有效,這個時候,優化器可能會選擇TABLE ACCESS FULL,可是若是換成了SELECT Y FROM T WHERE Y = XXX,優化器會直接去索引中找到Y的值,由於從B樹中就能夠找到相應的值。 索引
二、若是在B樹索引中有一個空值,那麼查詢諸如SELECT COUNT(*) FROM T 的時候,由於HASHSET中不能存儲空值的,因此優化器不會走索引,有兩種方式可讓索引有效,一種是SELECT COUNT(*) FROM T WHERE XXX IS NOT NULL或者是不能爲空。 get
三、若是在T表上有一個索引Y,可是你的查詢語句是這樣子SELECT * FROM T WHERE FUN(Y) = XXX。這個時候索引也不會被用到,由於你要查詢的列中全部的行都須要被計算一遍,所以,若是要讓這種sql語句的效率提升的話,在這個表上創建一個基於函數的索引,好比CREATE INDEX IDXFUNT ON T(FUN(Y));這種方式,等於Oracle會創建一個存儲全部函數計算結果的值,再進行查詢的時候就不須要進行計算了,由於不少函數存在不一樣返回值,所以必須標明這個函數是有固定返回值的。 效率
四、索引不適用於隱式轉換的狀況,好比你的SELECT * FROM T WHERE Y = 5 在Y上面有一個索引,可是Y列是VARCHAR2的,那麼Oracle會將上面的5進行一個隱式的轉換,SELECT * FROM T WHERE TO_NUMBER(Y) = 5,這個時候也是有可能用不到索引的。 sql語句
五、在Oracle的初始化參數中,有一個參數是一次讀取的數據塊的數目,好比你的表只有幾個數據塊大小,並且能夠被Oracle一次性抓取,那麼就沒有使用索引的必要了,由於抓取索引還須要去根據rowid從數據塊中獲取相應的元素值,所以在表特別小的狀況下,索引沒有用到是情理當中的事情。
六、很長時間沒有作表分析,或者從新收集表狀態信息了,在數據字典中,表的統計信息是不許確的,這個狀況下,可能會使用錯誤的索引,這個效率可能也是比較低的。
在《Oracle專家編程》這本書中,有一個很是不錯的例子,在本機實際作一下,能對索引有一個更深的印象,大體就是
CREATE TABLE FOO(USERNAME VARCHAR2(100) PRIMARY KEY,USERID VARCHAR2(100));
產生一堆數據,而後查詢SQL
CREATE TABLE FOOBAK SELECT * FROM FOO ORDER BY USERID DESC;
而後給USERNAME加上主鍵索引,而後查詢SQL
可以看到兩個使用了USERNAME pk 的索引,產生了不一樣的執行計劃,這個實實在在的說明了表的物理結構實實在在的影響了執行計劃。