1. 程式人生 > >Oracle SQL優化

Oracle SQL優化

column 第一個 inter scan 方法 舉例 全表掃描 span int

概述:

一、Oracle的優化器

Oracle的優化器共有兩種模式:RBO (基於規則)和CBO(基於成本)
RBO方式:優化器在分析SQL語句時,所遵循的是Oracle內部預定的一些規則。比如我們常見的,當一個where子句中的一列有索引時去走索引。
CBO方式:它是看語句的代價(Cost),這裏的代價主要指Cpu和內存。優化器在判斷是否用這種方式時,主要參照的是表及索引的統計信息。統計信息給出表的大小、有少行、每行的長度等信息。這些統計信息起初在庫內是沒有的,是通過對表進行分析後才出現的,很多時侯過期統計信息會令優化器做出一個錯誤的執行計劃,因些應及時更新這些信息。
CBO和RBO作為不同的SQL優化器,對SQL語句的執行計劃產生重大影響。

二、SQL優化的一般性原則:

目標:
減少服務器資源消耗(主要是磁盤IO);
設計方面:
盡量依賴oracle的優化器,並為其提供條件;
合適的索引,索引的雙重效應,列的選擇性;
編碼方面:
利用索引,避免大表FULL TABLE SCAN;
合理使用臨時表;
避免寫過於復雜的sql,不一定非要一個sql解決問題;
在不影響業務的前提下減小事務的粒度

三、具體如何優化,舉例?

1、通常我們在SELECT子句中列出所有的COLUMN時,使用動態SQL列引用 ‘*’ 是一個方便的方法.不幸的是,這是一個非常低效的方法.

  實際上,ORACLE在解析的過程中, 會將’*’ 依次轉換成所有的列名, 這個工作是通過查詢數據字典完成的, 這意味著將耗費更多的時間。

2、帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL語句會啟動SQL引擎執行耗費資源的排序(SORT)功能. DISTINCT需要一次排序操作,

  而其他的至少需要執行兩次排序.例如,一個UNION查詢,其中每個查詢都帶有GROUP BY子句, GROUP BY會觸發嵌入排序(NESTED SORT) ;

  這樣, 每個查詢需要執行一次排序, 然後在執行UNION時, 又一個唯一排序(SORT UNIQUE)操作被執行而且它只能在前面的嵌入排序結束後才能

開始執行.嵌入的排序的深度會大大影響查詢的效率.通常, 帶有UNION, MINUS , INTERSECT的SQL語句都可以用其他方式重寫.

3、給優化器更明確的命令

  【1】如果表中有兩個以上(包括兩個)索引,其中有一個唯一性索引,而其他是非唯一性.在這種情況下,ORACLE將使用唯一性索引而完全忽略非唯
  一性索引。

  【2】WHERE子句中,如果索引列是函數的一部分.優化器將不使用索引而使用全表掃描.
   如:

低效:
SELECT …
FROM DEPT
WHERE SAL * 12 > 25000;

高效:
SELECT …
FROM DEPT
WHERE SAL > 25000/12;

4、WHERE子句中, 如果索引列所對應的值的第一個字符由通配符(WILDCARD)開始, 索引將不被采用。這種情況下通常都是全表索引。

  如:

  SELECT USER_NO,USER_NAME,ADDRESS FROM USER_FILES WHERE USER_NO LIKE ‘%109204421‘;
5、通常,我們要避免在索引列上使用NOT, NOT會產生在和在索引列上使用函數相同的影響. 當ORACLE”遇到”NOT,他就會停止使用索引轉而執行全表掃描。
  如:

  低效: (這裏,不使用索引)
SELECT …
FROM DEPT
WHERE DEPT_CODE NOT = 0;

高效: (這裏,使用了索引)
SELECT …
FROM DEPT
WHERE DEPT_CODE > 0;

6、任何在where子句中使用is null或is not null的語句優化器是不允許使用索引的。
  如果唯一性索引建立在表的A列和B列上, 並且表中存在一條記錄的A,B值為(123,null) , ORACLE將不接受下一條具有相同A,B值(123,null)的記錄(插   入). 然而如果所有的索引列都為空,ORACLE將認為整個鍵值為空而空不等於空. 因此你可以插入1000條具有相同鍵值的記錄,當然它們都是空!

Oracle SQL優化