本站不再更新,歡迎光臨 java開發(fā)技術(shù)網(wǎng)
          隨筆-230  評論-230  文章-8  trackbacks-0
           1. 選用適合的ORACLE優(yōu)化器
            ORACLE的優(yōu)化器共有3種:
            a. RULE (基于規(guī)則)  b. COST (基于成本) c. CHOOSE (選擇性)
            設(shè)置缺省的優(yōu)化器,可以通過對init.ora文件中OPTIMIZER_MODE參數(shù)的各種聲明,如RULE,COST,CHOOSE,ALL_ROWS,FIRST_ROWS . 你當然也在SQL句級或是會話(session)級對其進行覆蓋.
            
            為了使用基于成本的優(yōu)化器(CBO, Cost-Based Optimizer) , 你必須經(jīng)常運行analyze 命令,以增加數(shù)據(jù)庫中的對象統(tǒng)計信息(object statistics)的準確性.
            
            如果數(shù)據(jù)庫的優(yōu)化器模式設(shè)置為選擇性(CHOOSE),那么實際的優(yōu)化器模式將和是否運行過analyze命令有關(guān). 如果table已經(jīng)被analyze過, 優(yōu)化器模式將自動成為CBO , 反之,數(shù)據(jù)庫將采用RULE形式的優(yōu)化器.
            
            在缺省情況下,ORACLE采用CHOOSE優(yōu)化器, 為了避免那些不必要的全表掃描(full table scan) , 你必須盡量避免使用CHOOSE優(yōu)化器,而直接采用基于規(guī)則或者基于成本的優(yōu)化器.
            2.    訪問Table的方式
            ORACLE 采用兩種訪問表中記錄的方式:
            a.    全表掃描
                全表掃描就是順序地訪問表中每條記錄. ORACLE采用一次讀入多個數(shù)據(jù)塊(database block)的方式優(yōu)化全表掃描.
            b.    通過ROWID訪問表
              你可以采用基于ROWID的訪問方式情況,提高訪問表的效率, , ROWID包含了表中記錄的物理位置信息..ORACLE采用索引(INDEX)實現(xiàn)了數(shù)據(jù)和存放數(shù)據(jù)的物理位置(ROWID)之間的聯(lián)系. 通常索引提供了快速訪問ROWID的方法,因此那些基于索引列的查詢就可以得到性能上的提高.
            
            3.    共享SQL語句
            
            為了不重復(fù)解析相同的SQL語句,在第一次解析之后, ORACLE將SQL語句存放在內(nèi)存中.這塊位于系統(tǒng)全局區(qū)域SGA(system global area)的共享池(shared buffer pool)中的內(nèi)存可以被所有的數(shù)據(jù)庫用戶共享. 因此,當你執(zhí)行一個SQL語句(有時被稱為一個游標)時,如果它
            
            和之前的執(zhí)行過的語句完全相同, ORACLE就能很快獲得已經(jīng)被解析的語句以及最好的
            
            執(zhí)行路徑. ORACLE的這個功能大大地提高了SQL的執(zhí)行性能并節(jié)省了內(nèi)存的使用.
            
             可惜的是ORACLE只對簡單的表提供高速緩沖(cache buffering) ,這個功能并不適用于多表連接查詢.
            
            數(shù)據(jù)庫管理員必須在init.ora中為這個區(qū)域設(shè)置合適的參數(shù),當這個內(nèi)存區(qū)域越大,就可以保留更多的語句,當然被共享的可能性也就越大了.
            
            當你向ORACLE 提交一個SQL語句,ORACLE會首先在這塊內(nèi)存中查找相同的語句.
            
             這里需要注明的是,ORACLE對兩者采取的是一種嚴格匹配,要達成共享,SQL語句必須
            
            完全相同(包括空格,換行等).
            
             共享的語句必須滿足三個條件:
            A.   字符級的比較:
            
            當前被執(zhí)行的語句和共享池中的語句必須完全相同.
            
             例如:
            
               SELECT * FROM EMP;
            
             和下列每一個都不同
            
               SELECT * from EMP;
            
               Select * From Emp;
            
               SELECT   *   FROM EMP;
            
            B.   兩個語句所指的對象必須完全相同:
            
            例如:
             
            考慮一下下列SQL語句能否在這兩個用戶之間共享.
            
            C.   兩個SQL語句中必須使用相同的名字的綁定變量(bind variables)
            例如:
            第一組的兩個SQL語句是相同的(可以共享),而第二組中的兩個語句是不同的(即使在運行時,賦于不同的綁定變量相同的值)
            a.
            
            select pin , name from people where pin = :blk1.pin;
            
            select pin , name from people where pin = :blk1.pin;
            
            b.
            
            select pin , name from people where pin = :blk1.ot_ind;
            select pin , name from people where pin = :blk1.ov_ind;


          4. 選擇最有效率的表名順序(只在基于規(guī)則的優(yōu)化器中有效)

            ORACLE的解析器按照從右到左的順序處理FROM子句中的表名,因此FROM子句中寫在最后的表(基礎(chǔ)表 driving table)將被最先處理. 在FROM子句中包含多個表的情況下,你必須選擇記錄條數(shù)最少的表作為基礎(chǔ)表.當ORACLE處理多個表時, 會運用排序及合并的方式連接它們.首先,掃描第一個表(FROM子句中最后的那個表)并對記錄進行派序,然后掃描第二個表(FROM子句中最后第二個表),最后將所有從第二個表中檢索出的記錄與第一個表中合適記錄進行合并.
            
            例如:
            
             表 TAB1 16,384 條記錄
            
             表 TAB2 1 條記錄
             選擇TAB2作為基礎(chǔ)表 (最好的方法)
            
             select count(*) from tab1,tab2 執(zhí)行時間0.96秒
            
             選擇TAB2作為基礎(chǔ)表 (不佳的方法)
             select count(*) from tab2,tab1 執(zhí)行時間26.09秒

            如果有3個以上的表連接查詢, 那就需要選擇交叉表(intersection table)作為基礎(chǔ)表, 交叉表是指那個被其他表所引用的表.

            例如:

             EMP表描述了LOCATION表和CATEGORY表的交集.

             SELECT *
            
            FROM LOCATION L ,
            
             CATEGORY C,
            
             EMP E
            
            WHERE E.EMP_NO BETWEEN 1000 AND 2000
            
            AND E.CAT_NO = C.CAT_NO
            
            AND E.LOCN = L.LOCN

            將比下列SQL更有效率

            SELECT *
            
            FROM EMP E ,
            
            LOCATION L ,
            
             CATEGORY C
            
            WHERE E.CAT_NO = C.CAT_NO
            
            AND E.LOCN = L.LOCN
            
            AND E.EMP_NO BETWEEN 1000 AND 2000

            
            5. WHERE子句中的連接順序.

            ORACLE采用自下而上的順序解析WHERE子句,根據(jù)這個原理,表之間的連接必須寫在其他WHERE條件之前, 那些可以過濾掉最大數(shù)量記錄的條件必須寫在WHERE子句的末尾.

            例如:

            (低效,執(zhí)行時間156.3秒)
            
            SELECT …
            
            FROM EMP E
            
            WHERE SAL > 50000
            
            AND JOB = ‘MANAGER’
            
            AND 25 < (SELECT COUNT(*) FROM EMP
            
             WHERE MGR=E.EMPNO);
            
            (高效,執(zhí)行時間10.6秒)
            
            SELECT …
            
            FROM EMP E
            
            WHERE 25 < (SELECT COUNT(*) FROM EMP
            
             WHERE MGR=E.EMPNO)
            
            AND SAL > 50000
            
            AND JOB = ‘MANAGER’;
            
            6. SELECT子句中避免使用 ‘ * ‘
            
            當你想在SELECT子句中列出所有的COLUMN時,使用動態(tài)SQL列引用 ‘*’ 是一個方便的方法.不幸的是,這是一個非常低效的方法. 實際上,ORACLE在解析的過程中, 會將’*’ 依次轉(zhuǎn)換成所有的列名, 這個工作是通過查詢數(shù)據(jù)字典完成的, 這意味著將耗費更多的時間.
            
            7. 減少訪問數(shù)據(jù)庫的次數(shù)
            
            當執(zhí)行每條SQL語句時, ORACLE在內(nèi)部執(zhí)行了許多工作: 解析SQL語句, 估算索引的利用率, 綁定變量 , 讀數(shù)據(jù)塊等等. 由此可見, 減少訪問數(shù)據(jù)庫的次數(shù) , 就能實際上減少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;
            
            
            注意:
            
             在SQL*Plus , SQL*Forms和Pro*C中重新設(shè)置ARRAYSIZE參數(shù), 可以增加每次數(shù)據(jù)庫訪問的檢索數(shù)據(jù)量 ,建議值為200


           8. 使用DECODE函數(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ù)也可以運用于GROUP BY 和ORDER BY子句中.
            
            
            
            
            
            9. 整合簡單,無關(guān)聯(lián)的數(shù)據(jù)庫訪問
            
            
            
            如果你有幾個簡單的數(shù)據(jù)庫查詢語句,你可以把它們整合到一個查詢中(即使它們之間沒有關(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個查詢可以被合并成一個:
            
            
            
            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’;
            
            
            
            (譯者按: 雖然采取這種方法,效率得到提高,但是程序的可讀性大大降低,所以讀者 還是要權(quán)衡之間的利弊)
            
            
            
            10. 刪除重復(fù)記錄
            
            最高效的刪除重復(fù)記錄方法 ( 因為使用了ROWID)
            
            
            
            DELETE FROM EMP E
            
            WHERE E.ROWID > (SELECT MIN(X.ROWID)
            
             FROM EMP X
            
             WHERE X.EMP_NO = E.EMP_NO);
            
            
            
            11. 用TRUNCATE替代DELETE
            
            當刪除表中的記錄時,在通常情況下, 回滾段(rollback segments ) 用來存放可以被恢復(fù)的信息. 如果你沒有COMMIT事務(wù),ORACLE會將數(shù)據(jù)恢復(fù)到刪除之前的狀態(tài)(準確地說是
            
            恢復(fù)到執(zhí)行刪除命令之前的狀況)
            
            
            
            而當運用TRUNCATE時, 回滾段不再存放任何可被恢復(fù)的信息.當命令運行后,數(shù)據(jù)不能被恢復(fù).因此很少的資源被調(diào)用,執(zhí)行時間也會很短.
            
            12. 盡量多使用COMMIT
            
            
            只要有可能,在程序中盡量多使用COMMIT, 這樣程序的性能得到提高,需求也會因為COMMIT所釋放的資源而減少:
             COMMIT所釋放的資源:
            
            a. 回滾段上用于恢復(fù)數(shù)據(jù)的信息.
            
            b. 被程序語句獲得的鎖
            
            c. redo log buffer 中的空間
            
            d. ORACLE為管理上述3種資源中的內(nèi)部花費

          13. 計算記錄條數(shù)
            
             和一般的觀點相反, count(*) 比count(1)稍快 , 當然如果可以通過索引檢索,對索引列的計數(shù)仍舊是最快的. 例如 COUNT(EMPNO)
            
            
            
            (譯者按: 在CSDN論壇中,曾經(jīng)對此有過相當熱烈的討論, 作者的觀點并不十分準確,通過實際的測試,上述三種方法并沒有顯著的性能差別)
            
            
            
            14. 用Where子句替換HAVING子句
            
            
            
             避免使用HAVING子句, HAVING 只會在檢索出所有記錄之后才對結(jié)果集進行過濾. 這個處理需要排序,總計等操作. 如果能通過WHERE子句限制記錄的數(shù)目,那就能減少這方面的開銷.
            
            
            
            例如:
            
            
            
             低效:
            
             SELECT REGION,AVG(LOG_SIZE)
            
             FROM LOCATION
            
             GROUP BY REGION
            
             HAVING REGION REGION != ‘SYDNEY’
            
             AND REGION != ‘PERTH’
            
            
            
             高效
            
             SELECT REGION,AVG(LOG_SIZE)
            
             FROM LOCATION
            
             WHERE REGION REGION != ‘SYDNEY’
            
             AND REGION != ‘PERTH’
            
             GROUP BY REGION
            
            (譯者按: HAVING 中的條件一般用于對一些集合函數(shù)的比較,如COUNT() 等等. 除此而外,一般的條件應(yīng)該寫在WHERE子句中)
            
            
            
            15. 減少對表的查詢
            
            在含有子查詢的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;
            
            
            
            
            
            16. 通過內(nèi)部函數(shù)提高SQL效率.
            
            
            
             SELECT H.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC,COUNT(*)
            
             FROM HISTORY_TYPE T,EMP E,EMP_HISTORY H
            
             WHERE H.EMPNO = E.EMPNO
            
            AND H.HIST_TYPE = T.HIST_TYPE
            
            GROUP BY H.EMPNO,E.ENAME,H.HIST_TYPE,T.TYPE_DESC;
            
            
            
            通過調(diào)用下面的函數(shù)可以提高效率.
            
            FUNCTION LOOKUP_HIST_TYPE(TYP IN NUMBER) RETURN VARCHAR2
            
            AS
            
             TDESC VARCHAR2(30);
            
             CURSOR C1 IS
            
             SELECT TYPE_DESC
            
             FROM HISTORY_TYPE
            
             WHERE HIST_TYPE = TYP;
            
            BEGIN
            
             OPEN C1;
            
             FETCH C1 INTO TDESC;
            
             CLOSE C1;
            
             RETURN (NVL(TDESC,’?’));
            
            END;

            FUNCTION LOOKUP_EMP(EMP IN NUMBER) RETURN VARCHAR2
            
            AS
            
             ENAME VARCHAR2(30);
            
             CURSOR C1 IS
            
             SELECT ENAME
            
             FROM EMP
            
             WHERE EMPNO=EMP;
            
            BEGIN
            
             OPEN C1;
            
             FETCH C1 INTO ENAME;
            
             CLOSE C1;
            
             RETURN (NVL(ENAME,’?’));
            
            END;
            SELECT H.EMPNO,LOOKUP_EMP(H.EMPNO),
            
            H.HIST_TYPE,LOOKUP_HIST_TYPE(H.HIST_TYPE),COUNT(*)
            
            FROM EMP_HISTORY H
            
            GROUP BY H.EMPNO , H.HIST_TYPE;
           17. 使用表的別名(Alias)
            
            當在SQL語句中連接多個表時, 請使用表的別名并把別名前綴于每個Column上.這樣一來,就可以減少解析的時間并減少那些由Column歧義引起的語法錯誤.

            (譯者注: Column歧義指的是由于SQL中不同的表具有相同的Column名,當SQL語句中出現(xiàn)這個Column時,SQL解析器無法判斷這個Column的歸屬)

            18. 用EXISTS替代IN
            
            在許多基于基礎(chǔ)表的查詢中,為了滿足一個條件,往往需要對另一個表進行聯(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’)
             (譯者按: 相對來說,用NOT EXISTS替換NOT IN 將更顯著地提高效率,下一節(jié)中將指出)

            
            19. 用NOT EXISTS替代NOT IN
            
            在子查詢中,NOT IN子句將執(zhí)行一個內(nèi)部的排序和合并. 無論在哪種情況下,NOT IN都是最低效的 (因為它對子查詢中的表執(zhí)行了一個全表遍歷). 為了避免使用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’);
            
           20. 用表連接替換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’ ;

            (譯者按: 在RBO的情況下,前者的執(zhí)行路徑包括FILTER,后者使用NESTED LOOP)

            21. 用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核心模塊將在子查詢的條件一旦滿足后,立刻返回結(jié)果.

            22. 識別’低效執(zhí)行’的SQL語句

            用下列SQL工具找出低效SQL:
            
            
            
            SELECT EXECUTIONS , DISK_READS, BUFFER_GETS,
            
             ROUND((BUFFER_GETS-DISK_READS)/BUFFER_GETS,2) Hit_radio,
            
             ROUND(DISK_READS/EXECUTIONS,2) Reads_per_run,
            
             SQL_TEXT
            
            FROM V$SQLAREA
            
            WHERE EXECUTIONS>0
            
            AND BUFFER_GETS > 0
            
            AND (BUFFER_GETS-DISK_READS)/BUFFER_GETS < 0.8
            
            ORDER BY 4 DESC;

            (譯者按: 雖然目前各種關(guān)于SQL優(yōu)化的圖形化工具層出不窮,但是寫出自己的SQL工具來解決問題始終是一個最好的方法)

            23. 使用TKPROF 工具來查詢SQL性能狀態(tài)

            SQL trace 工具收集正在執(zhí)行的SQL的性能狀態(tài)數(shù)據(jù)并記錄到一個跟蹤文件中. 這個跟蹤文件提供了許多有用的信息,例如解析次數(shù).執(zhí)行次數(shù),CPU使用時間等.這些數(shù)據(jù)將可以用來優(yōu)化你的系統(tǒng).

            設(shè)置SQL TRACE在會話級別: 有效

             ALTER SESSION SET SQL_TRACE TRUE

            設(shè)置SQL TRACE 在整個數(shù)據(jù)庫有效仿, 你必須將SQL_TRACE參數(shù)在init.ora中設(shè)為TRUE, USER_DUMP_DEST參數(shù)說明了生成跟蹤文件的目錄

            24. 用EXPLAIN PLAN 分析SQL語句
            EXPLAIN PLAN 是一個很好的分析SQL語句的工具,它甚至可以在不執(zhí)行SQL的情況下分析語句. 通過分析,我們就可以知道ORACLE是怎么樣連接表,使用什么方式掃描表(索引掃描或全表掃描)以及使用到的索引名稱.
            
            你需要按照從里到外,從上到下的次序解讀分析的結(jié)果. EXPLAIN PLAN分析的結(jié)果是用縮進的格式排列的, 最內(nèi)部的操作將被最先解讀, 如果兩個操作處于同一層中,帶有最小操作號的將被首先執(zhí)行.
            
            NESTED LOOP是少數(shù)不按照上述規(guī)則處理的操作, 正確的執(zhí)行路徑是檢查對NESTED LOOP提供數(shù)據(jù)的操作,其中操作號最小的將被最先處理.

            譯者按:

            通過實踐, 感到還是用SQLPLUS中的SET TRACE 功能比較方便.
            
            舉例:
            
            
            
            SQL> list
            
             1 SELECT *
            
             2 FROM dept, emp
            
             3* WHERE emp.deptno = dept.deptno
            
            SQL> set autotrace traceonly /*traceonly 可以不顯示執(zhí)行結(jié)果*/
            
            SQL> /
            
            14 rows selected.
            
            Execution Plan
            
            ----------------------------------------------------------
            
             0 SELECT STATEMENT Optimizer=CHOOSE
            
             1 0 NESTED LOOPS
            
             2 1 TABLE ACCESS (FULL) OF 'EMP'
            
             3 1 TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
            
             4 3 INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
            
            
            
            Statistics
            
            ----------------------------------------------------------
            
             0 recursive calls
            
             2 db block gets
            
             30 consistent gets
            
             0 physical reads
            
             0 redo size
            
             2598 bytes sent via SQL*Net to client
            
             503 bytes received via SQL*Net from client
            
             2 SQL*Net roundtrips to/from client
            
             0 sorts (memory)
            
             0 sorts (disk)
            
             14 rows processed
            
            
            
            通過以上分析,可以得出實際的執(zhí)行步驟是:
            
            1. TABLE ACCESS (FULL) OF 'EMP'
            
            2. INDEX (UNIQUE SCAN) OF 'PK_DEPT' (UNIQUE)
            
            3. TABLE ACCESS (BY INDEX ROWID) OF 'DEPT'
            
            4. NESTED LOOPS (JOINING 1 AND 3)
            
            注: 目前許多第三方的工具如TOAD和ORACLE本身提供的工具如OMS的SQL Analyze都提供了極其方便的EXPLAIN PLAN工具.也許喜歡圖形化界面的朋友們可以選用它們.
           
            


          posted on 2006-09-06 14:29 有貓相伴的日子 閱讀(854) 評論(0)  編輯  收藏 所屬分類: pl/sql
          本站不再更新,歡迎光臨 java開發(fā)技術(shù)網(wǎng)
          主站蜘蛛池模板: 永德县| 锦屏县| 察雅县| 台中市| 射阳县| 万山特区| 黄浦区| 丹棱县| 台南市| 三门县| 海宁市| 开鲁县| 辰溪县| 华宁县| 郧西县| 宜都市| 阿拉善左旗| 西宁市| 屏东县| 姚安县| 济源市| 锡林浩特市| 芦溪县| 临洮县| 平乐县| 东阳市| 雷波县| 宁安市| 罗平县| 乌兰浩特市| 乌苏市| 北碚区| 新巴尔虎左旗| 民和| 菏泽市| 兰州市| 建平县| 达拉特旗| 巨野县| 湘阴县| 壤塘县|