1.       用IN來替換OR
          下面的查詢可以被更有效率的語句替換:
          低效:
          SELECT field1, field1 FROM LOCATION
          WHERE LOC_ID = 10 OR     LOC_ID = 20 OR     LOC_ID = 30

          高效
          SELECT field1, field1 FROM LOCATION
          WHERE LOC_IN IN (10,20,30)    
          2.       連接多個掃描
          如果你對一個列和一組有限的值進行比較, 優化器可能執行多次掃描并對結果進行合并連接.
          舉例:
              SELECT * FROM LODGING
              WHERE MANAGER IN (‘BILL GATES’,’KEN MULLER’);
           
              優化器可能將它轉換成以下形式
              SELECT *  FROM LODGING
              WHERE MANAGER = ‘BILL GATES’
              OR MANAGER = ’KEN MULLER’;
          3.       優化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  
          4.       用>=替代>
          如果DEPTNO上有一個索引, 
          高效:
             SELECT *
             FROM EMP
             WHERE DEPTNO >=4
             
             低效:
             SELECT *
             FROM EMP
             WHERE DEPTNO >3

          5.       用表連接替換EXISTS
               通常來說 , 采用表連接的方式比EXISTS更有效率
                SELECT ENAME
                FROM EMP E
                WHERE EXISTS (SELECT ‘X’ 
                                FROM DEPT
                                WHERE DEPT_NO = E.DEPT_NO
                                AND DEPT_CAT = ‘A’);

               (更高效)
                SELECT ENAME
                FROM DEPT D,EMP E
                WHERE E.DEPT_NO = D.DEPT_NO
                AND DEPT_CAT = ‘A’ ; 
          6.       用EXISTS替換DISTINCT
          當提交一個包含一對多表信息(比如部門表和雇員表)的查詢時,避免在SELECT子句中使用DISTINCT. 一般可以考慮用EXIST替換 
          低效:
              SELECT DISTINCT DEPT_NO,DEPT_NAME
              FROM DEPT D,EMP E
              WHERE D.DEPT_NO = E.DEPT_NO
          高效:
              SELECT DEPT_NO,DEPT_NAME
              FROM DEPT D
              WHERE EXISTS ( SELECT ‘X’
                              FROM EMP E
                              WHERE E.DEPT_NO = D.DEPT_NO);

            EXISTS 使查詢更為迅速,因為RDBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結果.
          7.       使用表的別名(Alias)
          當在SQL語句中連接多個表時, 請使用表的別名并把別名前綴于每個Column上.這樣一來,就可以減少解析的時間并減少那些由Column歧義引起的語法錯誤.
          (譯者注: Column歧義指的是由于SQL中不同的表具有相同的Column名,當SQL語句中出現這個Column時,SQL解析器無法判斷這個Column的歸屬)

          8.       用EXISTS替代IN
          在許多基于基礎表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率.
          低效:
          SELECT * 
          FROM EMP (基礎表)
          WHERE EMPNO > 0
          AND DEPTNO IN (SELECT DEPTNO 
          FROM DEPT 
          WHERE LOC = ‘MELB’)
          高效: 
          SELECT * 
          FROM EMP (基礎表)
          WHERE EMPNO > 0
          AND EXISTS (SELECT ‘X’ 
          FROM DEPT 
          WHERE DEPT.DEPTNO = EMP.DEPTNO
          AND LOC = ‘MELB’)
           (譯者按: 相對來說,用NOT EXISTS替換NOT IN 將更顯著地提高效率,下一節中將指出)
          9.       用NOT EXISTS替代NOT IN
          在子查詢中,NOT IN子句將執行一個內部的排序和合并. 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執行了一個全表遍歷).  為了避免使用NOT IN ,我們可以把它改寫成外連接(Outer Joins)或NOT EXISTS.
          例如:
          SELECT …
          FROM EMP
          WHERE DEPT_NO NOT IN (SELECT DEPT_NO 
                                   FROM DEPT 
                                   WHERE DEPT_CAT=’A’);
          為了提高效率.改寫為:
          (方法一: 高效)
          SELECT ….
          FROM EMP A,DEPT B
          WHERE A.DEPT_NO = B.DEPT(+)
          AND B.DEPT_NO IS NULL
          AND B.DEPT_CAT(+) = ‘A’
          (方法二: 最高效)
          SELECT ….
          FROM EMP E
          WHERE NOT EXISTS (SELECT ‘X’ 
                              FROM DEPT D
                              WHERE D.DEPT_NO = E.DEPT_NO
                              AND DEPT_CAT = ‘A’);
          10.       減少對表的查詢
          在含有子查詢的SQL語句中,要特別注意減少對表的查詢.
          例如: 
               低效
                    SELECT TAB_NAME
                    FROM TABLES
                    WHERE TAB_NAME = ( SELECT TAB_NAME 
                                          FROM TAB_COLUMNS
                                          WHERE VERSION = 604)
                    AND DB_VER= ( SELECT DB_VER 
                                     FROM TAB_COLUMNS
                                     WHERE VERSION = 604)
               高效
                    SELECT TAB_NAME
                    FROM TABLES
                    WHERE  (TAB_NAME,DB_VER)
           = ( SELECT TAB_NAME,DB_VER) 
                             FROM TAB_COLUMNS
                             WHERE VERSION = 604)
               Update 多個Column 例子:
               低效:
                     UPDATE EMP
                     SET EMP_CAT = (SELECT MAX(CATEGORY) FROM EMP_CATEGORIES),
                        SAL_RANGE = (SELECT MAX(SAL_RANGE) FROM EMP_CATEGORIES)
                     WHERE EMP_DEPT = 0020;
               高效:
                     UPDATE EMP
                     SET (EMP_CAT, SAL_RANGE) 
          = (SELECT MAX(CATEGORY) , MAX(SAL_RANGE)
           FROM EMP_CATEGORIES)
                     WHERE EMP_DEPT = 0020;
          11. 在Oracle快速進行數據行存在性檢查
          只檢索一個啟示就可以判斷主鍵是否能與外鍵相配,這比Count(*)方法快得多,例如: 
          SQL Using Count(*) 
              SELECT Count(*) INTO :ll_Count
                 FROM ORDER
                 WHERE PROD_ID = :ls_CheckProd
                 USING SQLCA;
              
              IF ll_Count > 0 THEN // Cannot delete product 
          SQL Using ROWNUM
             SELECT ORDER_ID INTO :ll_OrderID
                 FROM ORDER
                 WHERE PROD_ID = :ls_CheckProd
                    AND ROWNUM < 2
                 USING SQLCA;

              IF SQLCA.SQLNRows <> 0 THEN // cannot delete product
          12 使用%TYPE、%ROWTYPE方式聲明變量
            程序設計中常常要通過變量來實現程序間的數據傳遞,即將表中數據賦值給變量,或是把變量值插入到表中。而要完成這些操作的前提就是,表中數據與變量類型要一致。然而在實際中,表中數據或類型、或寬度有時要變化,一旦變化,就必須去修改程序中的變量聲明部分,否則程序將不能正常運行。為了減少這部分程序的修改,編程時使用%TYPE、%ROWTYPE方式聲明變量,使變量聲明的類型與表中的保持同步,隨表的變化而變化,這樣的程序在一定程度上具有更強的通用性。
          13.       使用DECODE函數來減少處理時間
          使用DECODE函數可以避免重復掃描相同記錄或重復連接相同的表.
          例如:
             SELECT COUNT(*),SUM(SAL)
             FROM EMP
             WHERE DEPT_NO = 0020
             AND ENAME LIKE ‘SMITH%’;

             SELECT COUNT(*),SUM(SAL)
             FROM EMP
             WHERE DEPT_NO = 0030
             AND ENAME LIKE ‘SMITH%’;

          你可以用DECODE函數高效地得到相同結果

          SELECT COUNT(DECODE(DEPT_NO,0020,’X’,NULL)) D0020_COUNT,
                  COUNT(DECODE(DEPT_NO,0030,’X’,NULL)) D0030_COUNT,
                  SUM(DECODE(DEPT_NO,0020,SAL,NULL)) D0020_SAL,
                  SUM(DECODE(DEPT_NO,0030,SAL,NULL)) D0030_SAL
          FROM EMP WHERE ENAME LIKE ‘SMITH%’;

          類似的,DECODE函數也可以運用于GROUP BY 和ORDER BY子句中.
          14.       盡量多使用COMMIT
          只要有可能,在程序中盡量多使用COMMIT, 這樣程序的性能得到提高,需求也會因為COMMIT所釋放的資源而減少:
           COMMIT所釋放的資源:
          a.       回滾段上用于恢復數據的信息.
          b.       被程序語句獲得的鎖
          c.       redo log buffer 中的空間
          d.       ORACLE為管理上述3種資源中的內部花費
          15.       整合簡單,無關聯的數據庫訪問
          如果你有幾個簡單的數據庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關系)
          例如:

          SELECT NAME 
          FROM EMP 
          WHERE EMP_NO = 1234;

          SELECT NAME 
          FROM DPT
          WHERE DPT_NO = 10 ;

          SELECT NAME 
          FROM CAT
          WHERE CAT_TYPE = ‘RD’;

          上面的3個查詢可以被合并成一個:

          SELECT E.NAME , D.NAME , C.NAME
          FROM CAT C , DPT D , EMP E,DUAL X
          WHERE NVL(‘X’,X.DUMMY) = NVL(‘X’,E.ROWID(+))
          AND NVL(‘X’,X.DUMMY) = NVL(‘X’,D.ROWID(+))
          AND NVL(‘X’,X.DUMMY) = NVL(‘X’,C.ROWID(+))
          AND E.EMP_NO(+) = 1234
          AND D.DEPT_NO(+) = 10
          AND C.CAT_TYPE(+) = ‘RD’; 
          16.       WHERE子句中的連接順序.
          ORACLE采用自下而上的順序解析WHERE子句,根據這個原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數量記錄的條件必須寫在WHERE子句的末尾.
          例如:
          (低效,執行時間156.3秒)
          SELECT … 
          FROM EMP E
          WHERE  SAL > 50000
          AND    JOB = ‘MANAGER’
          AND    25 < (SELECT COUNT(*) FROM EMP
                       WHERE MGR=E.EMPNO);

          (高效,執行時間10.6秒)
          SELECT … 
          FROM EMP E
          WHERE 25 < (SELECT COUNT(*) FROM EMP
                       WHERE MGR=E.EMPNO)
          AND    SAL > 50000
          AND    JOB = ‘MANAGER’;
          17.     減少訪問數據庫的次數
          當執行每條SQL語句時, ORACLE在內部執行了許多工作: 解析SQL語句, 估算索引的利用率, 綁定變量 , 讀數據塊等等. 由此可見, 減少訪問數據庫的次數 , 就能實際上減少ORACLE的工作量.

          例如,
              以下有三種方法可以檢索出雇員號等于0342或0291的職員.

          方法1 (最低效)
              SELECT EMP_NAME , SALARY , GRADE
              FROM EMP 
              WHERE EMP_NO = 342;
               
              SELECT EMP_NAME , SALARY , GRADE
              FROM EMP 
              WHERE EMP_NO = 291;

          方法2 (次低效)
              
              DECLARE 
                  CURSOR C1 (E_NO NUMBER) IS 
                  SELECT EMP_NAME,SALARY,GRADE
                  FROM EMP 
                  WHERE EMP_NO = E_NO;
              BEGIN 
                  OPEN C1(342);
                  FETCH C1 INTO …,..,.. ;
                  …..
                  OPEN C1(291);
                 FETCH C1 INTO …,..,.. ;
                   CLOSE C1;
                END;

          方法3 (高效)

              SELECT A.EMP_NAME , A.SALARY , A.GRADE,
                      B.EMP_NAME , B.SALARY , B.GRADE
              FROM EMP A,EMP B
              WHERE A.EMP_NO = 342
              AND   B.EMP_NO = 291; 
          posted on 2008-09-20 15:32 李威威 閱讀(162) 評論(0)  編輯  收藏

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           
           
          主站蜘蛛池模板: 疏勒县| 城步| 钦州市| 连山| 大同市| 兴化市| 水富县| 德惠市| 葵青区| 历史| 丹东市| 海门市| 永济市| 鄂托克前旗| 子长县| 凉山| 江油市| 潞西市| 高青县| 呼和浩特市| 沽源县| 曲水县| 宁阳县| 博野县| 斗六市| 云阳县| 天门市| 冀州市| 天等县| 彰武县| 临武县| 浑源县| 宜章县| 镇康县| 井陉县| 邢台市| 青冈县| 瓦房店市| 义马市| 资兴市| 辉县市|