1、如果檢索數據量超過30%的表中記錄數,使用索引將沒有顯著的效率提高
2、在特定情況下,使用索引也許會比全表掃描慢,但這是同一個數量級上的差距;而通常情況下,使用索引比全表掃描要快幾倍乃至幾千倍!
用索引提高效率
索引是表的一個概念部分,用來提高檢索數據的效率。實際上,ORACLE使用了一個復雜的自平衡B-tree結構。 通常,通過索引查詢數據比全表掃描要快。當ORACLE找出執行查詢和Update語句的最佳路徑時,ORACLE優化器將使用索引。同樣在聯結多個表時使用索引也可以提高效率。另一個使用索引的好處是,它提供了主鍵(primary key)的唯一性驗證。 除了那些LONG或LONG RAW數據類型, 你可以索引幾乎所有的列。通常, 在大型表中使用索引特別有效。當然,在掃描小表時,使用索引同樣能提高效率。
雖然使用索引能得到查詢效率的提高,但是我們也必須注意到它的代價。索引需要空間來存儲,也需要定期維護,每當有記錄在表中增減或索引列被修改時, 索引本身也會被修改。 這意味着每條記錄的INSERT , DELETE , UPDATE將為此多付出4 , 5 次的磁盤I/O。因為索引需要額外的存儲空間和處理,那些不必要的索引反而會使查詢反應時間變慢,所以索引不能盲目的建立。
建立索引
表的主鍵、外鍵必須有索引;
經常與其他表進行連接的表,在連接字段上應該建立索引,多表進行多字段連接,建議適當建立復合索引;
索引應該建立在查詢條件中進行比較的字段上,而不是建立在我們要找出來並且顯示的字段上;
在條件表達式中經常用到的不同值較多的列上建立檢索,在不同值少的列上不要建立索引; <段落> 比如在雇員表的“性別”列上只有“男”與“女”兩個不同值,因此就無必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴重降低更新速度。 <段落> 組合索引要盡量使關鍵查詢形成索引覆蓋,其前導列一定是使用最頻繁的列。
經常與其他表進行連接的表,在連接字段上應該建立索引,多表進行多字段連接,建議適當建立復合索引;
索引應該建立在查詢條件中進行比較的字段上,而不是建立在我們要找出來並且顯示的字段上;
在條件表達式中經常用到的不同值較多的列上建立檢索,在不同值少的列上不要建立索引; <段落> 比如在雇員表的“性別”列上只有“男”與“女”兩個不同值,因此就無必要建立索引。如果建立索引不但不會提高查詢效率,反而會嚴重降低更新速度。 <段落> 組合索引要盡量使關鍵查詢形成索引覆蓋,其前導列一定是使用最頻繁的列。
索引失效
1、IN、OR子句常會使用工作表
使索引失效。如果不產生大量重復值,可以考慮把子句拆開。拆開的子句中應該包含索引。例子如下: <段落> 如果在fields1和fields2上同時建立了索引,fields1為主索引 以下sql會用到索引 select * from tablename1 where fields1=’value1’ and fields2=’value2’ 以下sql不會用到索引 select * from tablename1 where fields1=’value1’ or fields2=’value2’
使索引失效。如果不產生大量重復值,可以考慮把子句拆開。拆開的子句中應該包含索引。例子如下: <段落> 如果在fields1和fields2上同時建立了索引,fields1為主索引 以下sql會用到索引 select * from tablename1 where fields1=’value1’ and fields2=’value2’ 以下sql不會用到索引 select * from tablename1 where fields1=’value1’ or fields2=’value2’
2、使用IS NULL 或IS NOT NULL
使用IS NULL 或IS NOT NULL同樣會限制索引的使用。因為NULL值並沒有被索引定義。在SQL語句中使用NULL會有很多的麻煩。因此建議開發人員在建表時,把需要索引的列設成NOT NULL。如果被索引的列在某些行中存在NULL值,就不會使用這個索引。也可以使用特定的值來代替NULL。
請避免在索引中使用任何可以為空的列,oracle將無法使用該索引。
對於單列索引,如果列包含空值,索引中將不存在此記錄;
對於復合索引,如果每個列都為空,索引中同樣不存在此記錄。如果至少有一個列不為空,則記錄存在於索引中
因為空值不存在於索引列中,所以where子句中對索引列進行空值比較將使oracle停用該索引
(索引失效)
使用IS NULL 或IS NOT NULL同樣會限制索引的使用。因為NULL值並沒有被索引定義。在SQL語句中使用NULL會有很多的麻煩。因此建議開發人員在建表時,把需要索引的列設成NOT NULL。如果被索引的列在某些行中存在NULL值,就不會使用這個索引。也可以使用特定的值來代替NULL。
請避免在索引中使用任何可以為空的列,oracle將無法使用該索引。
對於單列索引,如果列包含空值,索引中將不存在此記錄;
對於復合索引,如果每個列都為空,索引中同樣不存在此記錄。如果至少有一個列不為空,則記錄存在於索引中
因為空值不存在於索引列中,所以where子句中對索引列進行空值比較將使oracle停用該索引
(索引失效)
select … from department where dept_code is not null
3、條件字段使用函數和表達式
如果不使用基於函數的索引,那么在SQL語句的WHERE子句中對存在索引的列使用函數時,會使優化器忽略掉這些索引。下面的查詢不會使用索引(只要它不是基於函數的索引)
如果不使用基於函數的索引,那么在SQL語句的WHERE子句中對存在索引的列使用函數時,會使優化器忽略掉這些索引。下面的查詢不會使用索引(只要它不是基於函數的索引)
select empno,ename,deptno from emp where trunc(hiredate)='01-MAY-81';
把上面的語句改成下面的語句,這樣就可以通過索引進行查找。
select empno, ename, deptno from emp where hiredate < (to_date('01-MAY-81') + 0.9999);
請務必注意,檢索中不要對索引列進行處理,如:trim,to_date,類型轉換等操作,破壞索引,使用全表掃描,影響sql執行效率
<段落>
4、避免在索引列上使用計算
假如索引列是函數的一部分,優化器將不使用索引而使用全表掃描。
假如索引列是函數的一部分,優化器將不使用索引而使用全表掃描。
低效: SELECT … FROM DEPT WHERE SAL * 12 > 25000;
高效: SELECT … FROM DEPT WHERE SAL > 25000/12;
<段落>
5、比較不匹配的數據類型
比較不匹配的數據類型也是比較難於發現的性能問題之一。注意下面查詢的例子,account_number是一個VARCHAR2類型,在account_number字段上有索引。下面的語句將執行全表掃描。
比較不匹配的數據類型也是比較難於發現的性能問題之一。注意下面查詢的例子,account_number是一個VARCHAR2類型,在account_number字段上有索引。下面的語句將執行全表掃描。
select bank_name, address, city, state, zip from banks where account_number = 990354;
Oracle可以自動把where子句變成to_number(account_number)=990354,這樣就限制了索引的使用,改成下面的查詢就可以使用索引: select bank_name, address, city, state, zip from banks where account_number = '990354';
特別注意:不匹配的數據類型之間比較會讓Oracle自動限制索引的使用,即便對這個查詢執行Explain Plan也不能讓您明白為什么做了一次“全表掃描”。
6、帶通配符(%)的like語句
要求在職工表中查詢名字中包含cliton的人。可以采用如下的查詢SQL語句:
要求在職工表中查詢名字中包含cliton的人。可以采用如下的查詢SQL語句:
select * from employee where last_name like '%cliton%';
這里由於通配符(%)在搜尋詞首出現,所以Oracle系統不使用last_name的索引。在很多情況下可能無法避免這種情況,但是一定要心中有底,通配符如此使用會降低查詢速度。然而當通配符出現在字符串其他位置時,優化器就能利用索引。
在下面的查詢中索引得到了使用: select * from employee where last_name like 'c%';
7、Order by語句
ORDER BY語句決定了Oracle如何將返回的查詢結果排序。Order by語句對要排序的列沒有什么特別的限制,也可以將函數加入列中(象聯接或者附加等)。任何在Order by語句的非索引項或者有計算表達式都將降低查詢速度。仔細檢查order by語句以找出非索引項或者表達式,它們會降低性能。解決這個問題的辦法就是重寫order by語句以使用索引,也可以為所使用的列建立另外一個索引,同時應絕對避免在order by子句中使用表達式。
ORDER BY語句決定了Oracle如何將返回的查詢結果排序。Order by語句對要排序的列沒有什么特別的限制,也可以將函數加入列中(象聯接或者附加等)。任何在Order by語句的非索引項或者有計算表達式都將降低查詢速度。仔細檢查order by語句以找出非索引項或者表達式,它們會降低性能。解決這個問題的辦法就是重寫order by語句以使用索引,也可以為所使用的列建立另外一個索引,同時應絕對避免在order by子句中使用表達式。
8、大於或小於操作符
大於或小於操作符一般情況下是不用調整的,因為它有索引就會采用索引查找,但有的情況下可以對它進行優化。 如一個表有100萬記錄,一個數值型字段A,30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那么執行A>2與A>=3的效果就有很大的區別了,因為A>2時ORACLE會先找出為2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄索引。
大於或小於操作符一般情況下是不用調整的,因為它有索引就會采用索引查找,但有的情況下可以對它進行優化。 如一個表有100萬記錄,一個數值型字段A,30萬記錄的A=0,30萬記錄的A=1,39萬記錄的A=2,1萬記錄的A=3。那么執行A>2與A>=3的效果就有很大的區別了,因為A>2時ORACLE會先找出為2的記錄索引再進行比較,而A>=3時ORACLE則直接找到=3的記錄索引。