Oracle SQL優化
概述:
一、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語句都可以用其他方式重寫.
【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優化