1.       用IN來(lái)替換OR
          下面的查詢可以被更有效率的語(yǔ)句替換:
          低效:
          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.       連接多個(gè)掃描
          如果你對(duì)一個(gè)列和一組有限的值進(jìn)行比較, 優(yōu)化器可能執(zhí)行多次掃描并對(duì)結(jié)果進(jìn)行合并連接.
          舉例:
              SELECT * FROM LODGING
              WHERE MANAGER IN (‘BILL GATES’,’KEN MULLER’);
           
              優(yōu)化器可能將它轉(zhuǎn)換成以下形式
              SELECT *  FROM LODGING
              WHERE MANAGER = ‘BILL GATES’
              OR MANAGER = ’KEN MULLER’;
          3.       優(yōu)化GROUP BY
          提高GROUP BY 語(yǔ)句的效率, 可以通過(guò)將不需要的記錄在GROUP BY 之前過(guò)濾掉.下面兩個(gè)查詢返回相同結(jié)果但第二個(gè)明顯就快了許多.
          低效:
             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上有一個(gè)索引, 
          高效:
             SELECT *
             FROM EMP
             WHERE DEPTNO >=4
             
             低效:
             SELECT *
             FROM EMP
             WHERE DEPTNO >3

          5.       用表連接替換EXISTS
               通常來(lái)說(shuō) , 采用表連接的方式比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
          當(dāng)提交一個(gè)包含一對(duì)多表信息(比如部門表和雇員表)的查詢時(shí),避免在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 使查詢更為迅速,因?yàn)镽DBMS核心模塊將在子查詢的條件一旦滿足后,立刻返回結(jié)果.
          7.       使用表的別名(Alias)
          當(dāng)在SQL語(yǔ)句中連接多個(gè)表時(shí), 請(qǐng)使用表的別名并把別名前綴于每個(gè)Column上.這樣一來(lái),就可以減少解析的時(shí)間并減少那些由Column歧義引起的語(yǔ)法錯(cuò)誤.
          (譯者注: Column歧義指的是由于SQL中不同的表具有相同的Column名,當(dāng)SQL語(yǔ)句中出現(xiàn)這個(gè)Column時(shí),SQL解析器無(wú)法判斷這個(gè)Column的歸屬)

          8.       用EXISTS替代IN
          在許多基于基礎(chǔ)表的查詢中,為了滿足一個(gè)條件,往往需要對(duì)另一個(gè)表進(jìn)行聯(lián)接.在這種情況下, 使用EXISTS(或NOT EXISTS)通常將提高查詢的效率.
          低效:
          SELECT * 
          FROM EMP (基礎(chǔ)表)
          WHERE EMPNO > 0
          AND DEPTNO IN (SELECT DEPTNO 
          FROM DEPT 
          WHERE LOC = ‘MELB’)
          高效: 
          SELECT * 
          FROM EMP (基礎(chǔ)表)
          WHERE EMPNO > 0
          AND EXISTS (SELECT ‘X’ 
          FROM DEPT 
          WHERE DEPT.DEPTNO = EMP.DEPTNO
          AND LOC = ‘MELB’)
           (譯者按: 相對(duì)來(lái)說(shuō),用NOT EXISTS替換NOT IN 將更顯著地提高效率,下一節(jié)中將指出)
          9.       用NOT EXISTS替代NOT IN
          在子查詢中,NOT IN子句將執(zhí)行一個(gè)內(nèi)部的排序和合并. 無(wú)論在哪種情況下,NOT IN都是最低效的 (因?yàn)樗鼘?duì)子查詢中的表執(zhí)行了一個(gè)全表遍歷).  為了避免使用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.       減少對(duì)表的查詢
          在含有子查詢的SQL語(yǔ)句中,要特別注意減少對(duì)表的查詢.
          例如: 
               低效
                    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 多個(gè)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快速進(jìn)行數(shù)據(jù)行存在性檢查
          只檢索一個(gè)啟示就可以判斷主鍵是否能與外鍵相配,這比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方式聲明變量
            程序設(shè)計(jì)中常常要通過(guò)變量來(lái)實(shí)現(xiàn)程序間的數(shù)據(jù)傳遞,即將表中數(shù)據(jù)賦值給變量,或是把變量值插入到表中。而要完成這些操作的前提就是,表中數(shù)據(jù)與變量類型要一致。然而在實(shí)際中,表中數(shù)據(jù)或類型、或?qū)挾扔袝r(shí)要變化,一旦變化,就必須去修改程序中的變量聲明部分,否則程序?qū)⒉荒苷_\(yùn)行。為了減少這部分程序的修改,編程時(shí)使用%TYPE、%ROWTYPE方式聲明變量,使變量聲明的類型與表中的保持同步,隨表的變化而變化,這樣的程序在一定程度上具有更強(qiáng)的通用性。
          13.       使用DECODE函數(shù)來(lái)減少處理時(shí)間
          使用DECODE函數(shù)可以避免重復(fù)掃描相同記錄或重復(fù)連接相同的表.
          例如:
             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函數(shù)高效地得到相同結(jié)果

          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函數(shù)也可以運(yùn)用于GROUP BY 和ORDER BY子句中.
          14.       盡量多使用COMMIT
          只要有可能,在程序中盡量多使用COMMIT, 這樣程序的性能得到提高,需求也會(huì)因?yàn)镃OMMIT所釋放的資源而減少:
           COMMIT所釋放的資源:
          a.       回滾段上用于恢復(fù)數(shù)據(jù)的信息.
          b.       被程序語(yǔ)句獲得的鎖
          c.       redo log buffer 中的空間
          d.       ORACLE為管理上述3種資源中的內(nèi)部花費(fèi)
          15.       整合簡(jiǎn)單,無(wú)關(guān)聯(lián)的數(shù)據(jù)庫(kù)訪問(wèn)
          如果你有幾個(gè)簡(jiǎn)單的數(shù)據(jù)庫(kù)查詢語(yǔ)句,你可以把它們整合到一個(gè)查詢中(即使它們之間沒(méi)有關(guān)系)
          例如:

          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個(gè)查詢可以被合并成一個(gè):

          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子句,根據(jù)這個(gè)原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過(guò)濾掉最大數(shù)量記錄的條件必須寫在WHERE子句的末尾.
          例如:
          (低效,執(zhí)行時(shí)間156.3秒)
          SELECT … 
          FROM EMP E
          WHERE  SAL > 50000
          AND    JOB = ‘MANAGER’
          AND    25 < (SELECT COUNT(*) FROM EMP
                       WHERE MGR=E.EMPNO);

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

          例如,
              以下有三種方法可以檢索出雇員號(hào)等于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) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
           
          主站蜘蛛池模板: 翼城县| 开封市| 淮滨县| 习水县| 银川市| 常宁市| 滨州市| 中江县| 阳泉市| 临沭县| 宁都县| 平乐县| 北流市| 米易县| 南木林县| 道真| 滦南县| 隆安县| 新蔡县| 博野县| 澄城县| 廉江市| 灵璧县| 锦州市| 全州县| 黔东| 焦作市| 外汇| 仙居县| 新龙县| 黄大仙区| 纳雍县| 苗栗市| 靖江市| 江陵县| 汉川市| 湖北省| 栾川县| 巨野县| 福清市| 勃利县|