1. 程式人生 > >ORACLE索引使用總結(SQL優化及避免索引無效小技巧)

ORACLE索引使用總結(SQL優化及避免索引無效小技巧)

 

一:索引基本概念

oracle提供了兩種方式,從表中讀取所有行(即全表掃描),或者通過ROWID一次讀取一行;

如果只訪問大資料量表的5%的行,並且使用索引標識需要讀取的資料塊,這樣花費的 I/O 較少,索引對效能的改程序度: 1.取決於資料的選擇性 2.資料在表的資料塊中的分步方式;

當資料分散在表的多個數據塊時,最好是不使用索引,而是使用全表掃描,執行全表掃描時,oracle使用多塊讀取以快速掃描表,基於索引的讀是單塊讀,因此在使用索引時的目標是減少完成查詢所需的單塊讀的數量;

增強索引會降低 insert 語句的效能(因為需要同時對錶和索引進行更新),大量行的 delete 操作,將會由於表中存在索引而變慢;

在SQL中有許多陷阱會使一些索引無法使用:

1.使用不等於運算子(NOT、<>)

索引只能查詢表中已存在的資料,每當在 where 子句中使用不等於運算子時,其中被用到的列上的索引都將無法使用;例如:select cust_id, cust_name from customers where cust_rating <> 'aa'; oracle在分析表的同時收集資料分佈的相關統計資訊,通過這種方法,基於成本的優化器可以決定在where子句中對一些值使用索引,而對其他值不使用索引;

可以使用 create index 命令的 compute statistic 子句,在建立索引的同時分析它們;

2.使用 IS NULL

當在where子句中使用ISNULL的時候,因為NULL值並沒有被定義(oracle不會再B樹索引中對NULL值索引),所以索引的使用會被抑制,資料庫中沒有值等於NULL,甚至NULL也不等於NULL;如果被索引的列在某些行中存在NULL值,在索引中就不會有相應的條目(除非使用點陣圖索引,這是點陣圖索引對於NULL搜尋很快的原因);例如:select empno, deptno from emp where sal is null; 即使sal列上有索引,也會進行全表掃描;

3.使用LIKE

條件中有LIKE關鍵字會使用索引,通常有兩種寫法 LIKE '%some%' 或 LIKE ‘%some’ 或 LIKE ‘some%’ ;當%在前面的時候,索引不會被使用,但是當值在前面的時候,oracle可以使用索引;

4.使用函式

除非使用基於函式的索引,否則在SQL語句的where子句中對存在的索引的列使用函式時,優化器會忽略索引,一般常見的函式如:TRUNC, SUBSTR, TO_DATE, TO_CHAR 和 INSTR 等,

例如下面的SQL就會使用全表掃描,

select empno, deptno from emp where trunc(hiredate) = '01-MAY-01' ;

改成下面就可以了

select empno, deptno from emp where hiredate > '01-MAY-01' and hiredate < (TO_DATE('01-MAY-01' ) + 0.99999);

通過改變所比較列上的值,而不用改變列本身,就可以啟用索引,這樣可以避免全表掃描;

5.比較不匹配的資料型別(隱式轉換)

一種很難解決的效能問題是比較不匹配的資料型別,oracle不但不會對那些不相容的資料型別報錯,反而會做隱式資料轉換。例如:oracle可以隱式轉化 varchar2 型別的列中的資料去匹配數值型別資料;

如果account_number列是varchar2資料型別,下面將進行全表掃描: select bank_name, address, city, state, zip from banks where account_number = 99999; oracle會自動轉換成 to_number(account_number) = 99999 ; 這樣就抑制了索引的使用;

如果上面的語句加上單引號就會使用索引。select bank_name, address, city, state, zip from banks where account_number = '99999';

6.OR關鍵字的使用,會抑制索引,下面使用OR,即使是索引列,資料型別匹配,仍會抑制索引的使用

select bank_name, address, city, state, zip from banks where account_number = '99999' or account_number = '88888' ;

改成 AND 或 IN ,oracle就可以使用索引的

 

叢集因子

叢集因子(CLUSTERING_FACTOR)是對錶的有序性的量度,通過一個索引掃描一張表時需要訪問表的資料庫的數量;

一個欄位上有索引,但有時執行sql語句時看執行計劃時不走索引,就有可能是叢集因子過高導致的。

計算方法:1.掃描一個索引 2.標膠某行的 rowid 和前一行的 rowid,如果這兩個 rowid 不屬於同一個資料塊,那麼叢集因子+1 3.整個索引掃描完畢得到叢集因子的值

 

 

如果叢集因子接近於表中塊的數量,則表示索引適當排序;如果叢集因子接近於表中行的數量,則表示索引沒有適當排序

優化執行計劃總結

1.避免索引列的隱式轉換;

2.匹配索引的前導列(組合/複合索引):如果索引是建立在多個列上,只有在它的前導列被where子句引用時,優化器才會選擇使用該索引;

3.使用ROWID;

4.避免對索引列 使用 OR、函式運算(TRUNC、TO_DATE、TO_CHAR等)、計算等操作;可以使用AND、IN、UNION代替對索引列使用OR操作;

5.減少函式的呼叫;

6.減少語句中表的訪問次數;

7.避免笛卡爾集;