oracle sql 優化(三)

(23) 用>=替代> sql

高效: 數據庫

SELECT * FROM EMP WHERE DEPTNO >=4

低效: 函數

SELECT * FROM EMP WHERE DEPTNO >3

二者的區別在於, 前者DBMS將直接跳到第一個DEPT等於4的記錄然後者將首先定位到DEPTNO=3的記錄而且向前掃描到第一個DEPT大於3的記錄.優化

  (24) 用UNION替換OR (適用於索引列) spa

    一般狀況下, 用UNION替換WHERE子句中的OR將會起到較好的效果. 對索引列使用OR將形成全表掃描. 注意, 以上規則只針對多個索引列有效. 若是有column沒有被索引, 查詢效率可能會由於你沒有選擇OR而下降. 在下面的例子中, LOC_ID 和REGION上都建有索引. code

高效:排序

SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 
UNION 
SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE REGION = 「MELBOURNE」

低效:索引

SELECT LOC_ID , LOC_DESC , REGION FROM LOCATION WHERE LOC_ID = 10 OR REGION = 「MELBOURNE」

若是你堅持要用OR, 那就須要返回記錄最少的索引列寫在最前面. 
內存

  (25) 用IN來替換OR 資源

    這是一條簡單易記的規則,可是實際的執行效果還須檢驗,在ORACLE8i下,二者的執行路徑彷佛是相同的.  

低效:

SELECT…. FROM LOCATION WHERE LOC_ID = 10 OR LOC_ID = 20 OR LOC_ID = 30

高效

SELECT… FROM LOCATION WHERE LOC_IN IN (10,20,30);

  

(26) 避免在索引列上使用IS NULL和IS NOT NULL 

    避免在索引中使用任何能夠爲空的列,ORACLE將沒法使用該索引.對於單列索引,若是列包含空值,索引中將不存在此記錄. 對於複合索引,若是每一個列都爲空,索引中一樣不存在此記錄. 若是至少有一個列不爲空,則記錄存在於索引中.舉例: 若是惟一性索引創建在表的A列和B列上, 而且表中存在一條記錄的A,B值爲(123,null) , ORACLE將不接受下一條具備相同A,B值(123,null)的記錄(插入). 然而若是全部的索引列都爲空,ORACLE將認爲整個鍵值爲空,而空不等於空. 所以你能夠插入1000 條具備相同鍵值的記錄,固然它們都是空! 由於空值不存在於索引列中,因此WHERE子句中對索引列進行空值比較將使ORACLE停用該索引. 

低效: (索引失效)

SELECT … FROM DEPARTMENT WHERE DEPT_CODE IS NOT NULL;

高效: (索引有效)

SELECT … FROM DEPARTMENT WHERE DEPT_CODE >=0;

(27) 老是使用索引的第一個列: 

    若是索引是創建在多個列上, 只有在它的第一個列(leading column)被where子句引用時,優化器纔會選擇使用該索引. 這也是一條簡單而重要的規則,當僅引用索引的第二個列時,優化器使用了全表掃描而忽略了索引

(28) 用UNION-ALL 替換UNION ( 若是有可能的話): 
    當SQL語句須要UNION兩個查詢結果集合時,這兩個結果集合會以UNION-ALL的方式被合併, 而後在輸出最終結果前進行排序. 若是用UNION ALL替代UNION, 這樣排序就不是必要了. 效率就會所以獲得提升. 須要注意的是,UNION ALL 將重複輸出兩個結果集合中相同記錄. 所以各位仍是要從業務需求分析使用UNION ALL的可行性. UNION 將對結果集合排序,這個操做會使用到SORT_AREA_SIZE這塊內存. 對於這塊內存的優化也是至關重要的. 下面的SQL能夠用來查詢排序的消耗量 
低效: 

SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95' UNION SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95'

高效:

SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS
WHERE TRAN_DATE = '31-DEC-95' UNION ALL SELECT ACCT_NUM, BALANCE_AMT FROM DEBIT_TRANSACTIONS WHERE TRAN_DATE = '31-DEC-95'

(29) 用WHERE替代ORDER BY: 
ORDER BY 子句只在兩種嚴格的條件下使用索引. 
ORDER BY中全部的列必須包含在相同的索引中並保持在索引中的排列順序. 
ORDER BY中全部的列必須定義爲非空. 
WHERE子句使用的索引和ORDER BY子句中所使用的索引不能並列. 
例如: 表DEPT包含如下列: 
DEPT_CODE PK NOT NULL 
DEPT_DESC NOT NULL 
DEPT_TYPE NULL 
低效: (索引不被使用)

SELECT DEPT_CODE FROM DEPT ORDER BY DEPT_TYPE

高效: (使用索引)

SELECT DEPT_CODE FROM DEPT WHERE DEPT_TYPE > 0

(30) 避免改變索引列的類型.: 
    當比較不一樣數據類型的數據時, ORACLE自動對列進行簡單的類型轉換. 
假設 EMPNO是一個數值類型的索引列. SELECT … FROM EMP WHERE EMPNO = ‘123' 實際上,通過ORACLE類型轉換, 語句轉化爲: SELECT … FROM EMP WHERE EMPNO = TO_NUMBER(‘123') 幸運的是,類型轉換沒有發生在索引列上,索引的用途沒有被改變. 如今,假設EMP_TYPE是一個字符類型的索引列. SELECT … FROM EMP WHERE EMP_TYPE = 123 這個語句被ORACLE轉換爲: SELECT … FROM EMP WHERETO_NUMBER(EMP_TYPE)=123 由於內部發生的類型轉換, 這個索引將不會被用到! 爲了不ORACLE對你的SQL進行隱式的類型轉換, 最好把類型轉換用顯式表現出來. 注意當字符和數值比較時, ORACLE會優先轉換數值類型到字符類型 

(31) 須要小心的WHERE子句: 
    某些SELECT 語句中的WHERE子句不使用索引. 這裏有一些例子. 在下面的例子裏, (1)‘!=' 將不使用索引. 記住, 索引只能告訴你什麼存在於表中, 而不能告訴你什麼不存在於表中. (2) ‘||'是字符鏈接函數. 就象其餘函數那樣, 停用了索引. (3) ‘+'是數學函數. 就象其餘數學函數那樣, 停用了索引. (4)相同的索引列不能互相比較,這將會啓用全表掃描. 

(32) a. 若是檢索數據量超過30%的表中記錄數.使用索引將沒有顯著的效率提升. 
b. 在特定狀況下, 使用索引也許會比全表掃描慢, 但這是同一個數量級上的區別. 而一般狀況下,使用索引比全表掃描要塊幾倍乃至幾千倍! 

(33) 避免使用耗費資源的操做: 
    帶有DISTINCT,UNION,MINUS,INTERSECT,ORDER BY的SQL語句會啓動SQL引擎 執行耗費資源的排序(SORT)功能. DISTINCT須要一次排序操做, 而其餘的至少須要執行兩次排序. 一般, 帶有UNION, MINUS , INTERSECT的SQL語句均可以用其餘方式重寫. 若是你的數據庫的SORT_AREA_SIZE調配得好, 使用UNION , MINUS, INTERSECT也是能夠考慮的, 畢竟它們的可讀性很強(Oracle查詢運算:intersect和minus intersect運算 返回查詢結果中相同的部分 exp:各個部門中有哪些相同的工種 select job from account intersect select job from research intersect select job from sales; minus運算 返回在第一個查詢結果中與第二個查詢結果不相同的那部分行記錄。 有哪些工種在財會部中有,而在銷售部中沒有)

(34) 優化GROUP BY: 
    提升GROUP BY 語句的效率, 能夠經過將不須要的記錄在GROUP BY 以前過濾掉.下面兩個查詢返回相同結果但第二個明顯就快了許多. 
低效: 

SELECT JOB , AVG(SAL)
FROM EMP GROUP JOB HAVING JOB = ‘PRESIDENT' OR JOB = ‘MANAGER'

高效:

SELECT JOB , AVG(SAL)
FROM EMP
WHERE JOB = ‘PRESIDENT'
OR JOB = ‘MANAGER' GROUP JOB
相關文章
相關標籤/搜索