<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    The important thing in life is to have a great aim , and the determination

    常用鏈接

    統計

    IT技術鏈接

    保險相關

    友情鏈接

    基金知識

    生活相關

    最新評論

    使用EXPLAIN PLAN獲取SQL語句執行計劃

    SQL查詢語句的性能從一定程度上影響整個數據庫的性能。很多情況下,數據庫性能的低下差不多都是不良SQL語句所引起。而SQL語句的執行
    計劃則決定了SQL語句將會采用何種方式從數據庫提取數據并返回給客戶端,本文描述的將是如何通過EXPLAIN PLAN 獲取SQL語句執行計劃來獲
    取SQL語句的執行計劃。
    一、獲取SQL語句執行計劃的方式
         1. 使用explain plan 將執行計劃加載到表plan_table,然后查詢該表來獲取預估的執行計劃
         2. 查詢動態性能視圖v$sql_plan,v$sql_plan_statistics,v$sql_workarea 等來獲取已緩存到庫緩存中的真實執行計劃
         3. 查詢自動工作量資料庫(Automatic Workload Repository)或查詢Statspack,即從資料庫中獲取執行計劃
         4. 啟用執行計劃跟蹤功能,即autotrace功能
         5. 使用PL/SQL Developer提供的獲取執行計劃方法
         6. 使用Toad工具來獲取執行計劃
     下面主要討論使用explain plan獲取執行計劃的方法
    二、explain plan工作實質、前提及操作方法
         1. 工作實質
          將SQL語句預估的執行計劃加載到表plan_table,是對表plan_table 執行了DML操作,故不會執行隱式提交
          可以對select,insert,update,merge,delete,create table, create index,alter index等加載執行計劃到plan_table
         2. 前提條件
          需要先創建plan_table,創建方法:@?/rdbms/admin/utlxplan
          對當前的SQL語句有執行權限以及對依賴的對象有相應操作的權限
         3. 使用方法:
           explain plan for select * from scott.emp where ename='SCOTT';    --未設置標記位
           explain plan set statement_id='TEST' for select * from scott.emp where ename='SCOTT'  --設置標記位為TEST
    三、實戰演習
     1.環境 
     
    scott@ORCL> select * from v$version;                              
                                                                     
    BANNER                                                           
    ---------------------------------------------------------------- 
    Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod 
     2.創建測試表演示獲取執行計劃
     
    scott@ORCL> create table t as select * from all_objects where rownum<=1000;                                      
                                                                                                                      
    Table created.                                                                                                   
                                                                                                                      
    --加載創建表的執行計劃(DDL 執行計劃)                                                                             
    scott@ORCL> explain plan set statement_id='T1' for create table t1 as select * from t;                           
                                                                                                                      
    Explained.                                                                                                       
                                                                                                                      
    --使用下面的語句從plan_table 獲取執行計劃                                                                        
    col OPERATION format a25                                                                                          
    col OPTIONS format a25                                                                                           
    col OBJECT_NAME format a25                                                                                        
    SELECT lpad(' ', 2 * (LEVEL - 1)) || operation operation                                                         
        ,options                                                                                                     
        ,object_name                                                                                                 
        ,position pos                                                                                                
        ,bytes                                                                                                        
        ,cost                                                                                                        
    FROM plan_table                                                                                                   
    START WITH id = 0                                                                                                
    AND statement_id =upper( '&input_statement_id')                                                                   
    CONNECT BY PRIOR id = parent_id;                                                                                 
                                                                                                                      
    Enter value for input_statement_id: T1                                                                           
    old   9: AND statement_id =upper( '&input_statement_id')                                                         
    new   9: AND statement_id =upper( 'T1')                                                                          
                                                                                                                     
    OPERATION                 OPTIONS                   OBJECT_NAME                      POS      BYTES       COST   
    ------------------------- ------------------------- ------------------------- ---------- ---------- ----------   
    CREATE TABLE STATEMENT                                                                 8      79000          8   
      LOAD AS SELECT                                    T1                                 1                         
        TABLE ACCESS          FULL                      T                                  1      79000          5   
                                                                                                                     
    --創建測試表t1并收集統計信息                                                                                     
    scott@ORCL> create table t1 nologging as select * from t;                                                        
                                                                                                                     
    scott@ORCL> exec dbms_stats.gather_table_stats('SCOTT','T1');                                                    
                                                                                                                     
    --使用explain plan加載創建索引的執行計劃                                                                          
    scott@ORCL> explain plan set statement_id='IDX' for create index i_t1 on t1(object_id);                          
                                                                                                                      
    Explained.                                                                                                       
                                                                                                                     
    scott@ORCL> @Get_Plan                                                                                            
    Enter value for input_statement_id: IDX                                                                          
    old   9: AND statement_id =upper( '&input_statement_id')                                                         
    new   9: AND statement_id =upper( 'IDX')                                                                         
                                                                                                                      
    OPERATION                 OPTIONS                   OBJECT_NAME                      POS      BYTES       COST   
    ------------------------- ------------------------- ------------------------- ---------- ---------- ----------   
    CREATE INDEX STATEMENT                                                                 6       4000          6   
      INDEX BUILD             NON UNIQUE                I_T1                               1                          
        SORT                  CREATE INDEX                                                 1       4000              
          TABLE ACCESS        FULL                      T1                                 1       4000          5   
                                                                                                                     
    scott@ORCL> CREATE INDEX i_t1 ON t1 (object_id);                                                                 
                                                                                                                      
    scott@ORCL> delete from plan_table;           
     3.使用自頂向下的讀取方法獲取執行計劃
     
    --使用explain plan加載重建索引的執行計劃                                                                            
    scott@ORCL> explain plan set statement_id='A_IDX' for alter index i_t1 rebuild;                                    
                                                                                                                       
    Explained.                                                                                                          
                                                                                                                       
    --執行下面的語句來獲的A_IDX的執行計劃,其結果是從上至下來讀,從最內側往最外側讀。                                  
    SELECT LPAD(' ', 2 * (LEVEL - 1)) || LEVEL || '.' || NVL(POSITION, 0) || ' ' ||                                    
        OPERATION || ' ' || OPTIONS || ' ' || OBJECT_NAME || ' ' ||                                                     
        OBJECT_TYPE || ' ' ||                                                                                          
        DECODE(ID, 0, STATEMENT_ID || ' Cost = ' || POSITION) || COST || ' ' ||                                        
        OBJECT_NODE "Query Plan"                                                                                       
    FROM PLAN_TABLE                                                                                                    
    START WITH ID = 0                                                                                                   
    AND STATEMENT_ID = UPPER('&input_statement_id')                                                                    
    CONNECT BY PRIOR ID = PARENT_ID                                                                                     
    AND STATEMENT_ID = UPPER('&input_statement_id');                                                                   
                                                                                                                        
    Enter value for input_statement_id: A_IDX                                                                          
    old   8: AND STATEMENT_ID = UPPER('&input_statement_id')                                                            
    new   8: AND STATEMENT_ID = UPPER('A_IDX')                                                                         
    Enter value for input_statement_id: A_IDX                                                                           
    old  10: AND STATEMENT_ID = UPPER('&input_statement_id')                                                           
    new  10: AND STATEMENT_ID = UPPER('A_IDX')                                                                         
                                                                                                                       
    Query Plan                                                                                                         
    ---------------------------------------------------------------------------------------------                      
    1.2 ALTER INDEX STATEMENT    A_IDX Cost = 22                                                                       
      2.1 INDEX BUILD NON UNIQUE I_T1                                                                                   
        3.1 SORT CREATE INDEX                                                                                          
          4.1 INDEX FAST FULL SCAN I_T1 INDEX 2                                                                         
                                                                                                                       
    --使用explain plan加載查詢語句的執行計劃                                                                            
    scott@ORCL> explain plan set statement_id='QUERY' for                                                              
      2  select ename,dname                                                                                            
      3  from emp join dept                                                                                            
      4  on emp.deptno=dept.deptno                                                                                     
      5  where dept.deptno=30;                                                                                          
                                                                                                                       
    Explained.                                                                                                          
                                                                                                                       
    scott@ORCL> @Get_Plan2                                                                                              
                                                                                                                       
    Query Plan                                                                                                          
    --------------------------------------------------------------------------------------------                       
    1.4 SELECT STATEMENT    QUERY Cost = 44                                                                            
      2.1 NESTED LOOPS    4                                                                                            
        3.1 TABLE ACCESS BY INDEX ROWID DEPT TABLE 1                                                                   
          4.1 INDEX UNIQUE SCAN PK_DEPT INDEX (UNIQUE) 0                                                               
        3.2 TABLE ACCESS FULL EMP TABLE 3                                                                              
      上面的例子的讀取方法:
           執行4.1的索引唯一掃描
           將4.1的結果集返回給3.1
           執行3.2的全表掃描
           將3.1和3.2步驟的結果集返回給2.1
           執行2.1的嵌套循環
           返回最終結果集
           注意嵌套循環的查詢方法
           Oracle 從第一個行源中讀取第一行,然后和第二個行源中的所有記錄行進行比對,所有匹配的記錄放在結果集中,然后Oracle 將讀第一
           個行源中的下一行。依次類推,直到第一行源中的所有行處理完畢。
     4.使用構建樹方式查看執行計劃
     
    scott@ORCL> delete from plan_table;                                                                           
                                                                                                                  
    --使用explian plan加載SQL查詢執行計劃                                                                          
    scott@ORCL> explain plan set statement_id='QUERY2' for                                                        
      2  select ename,dname                                                                                        
      3  from emp join dept                                                                                       
      4  on emp.deptno=dept.deptno                                                                                
      5  where emp.empno=7788;                                                                                    
                                                                                                                  
    Explained.                                                                                                     
                                                                                                                  
    --使用下面的SQl查詢來生成構建樹                                                                                
    col operation format a30                                                                                      
    col options format a20                                                                                         
    col "OBJECT NAME" format a25                                                                                  
    col order format a10                                                                                          
    col opt format a15                                                                                             
    SELECT LPAD(' ', 2 * (LEVEL - 1)) || operation "OPERATION",                                                   
        options "OPTIONS",                                                                                        
        DECODE(TO_CHAR(id),                                                                                       
            '0',                                                                                                   
            'COST = ' || NVL(TO_CHAR(position), 'n/a'),                                                           
            object_name) "OBJECT NAME",                                                                            
        id || '-' || NVL(parent_id, 0) || '-' || NVL(position, 0) "ORDER",                                        
        SUBSTR(optimizer, 1, 6) "OPT"                                                                              
    FROM plan_table                                                                                               
    START WITH id = 0                                                                                             
    AND statement_id = UPPER('&input_statement_id')                                                               
    CONNECT BY PRIOR id = parent_id                                                                               
    AND statement_id = UPPER('&input_statement_id');                                                              
                                                                                                                  
    OPERATION                      OPTIONS              OBJECT NAME               ORDER      OPT                  
    ------------------------------ -------------------- ------------------------- ---------- ---------------      
    SELECT STATEMENT                                    COST = 2                  0-0-2      ALL_RO               
      NESTED LOOPS                                                                1-0-1                           
        TABLE ACCESS               BY INDEX ROWID       EMP                       2-1-1      ANALYZ               
          INDEX                    UNIQUE SCAN          PK_EMP                    3-2-1      ANALYZ               
        TABLE ACCESS               BY INDEX ROWID       DEPT                      4-1-2      ANALYZ               
          INDEX                    UNIQUE SCAN          PK_DEPT                   5-4-1      ANALYZ               
     
          查詢結果中的order列與opt列
          order
               order列的指名了ID,父ID,以及執行計劃中這一步驟的位置。
               ID列標識了這個步驟,但并沒有說明執行的順序
               父ID表明了這個步驟中的父步驟
               位置信息說明了父ID相同的子操作的執行順序    
          opt
               說明當前優化器使用的模式
          分析
               首先會從步驟3開始執行,步驟3通過索引唯一掃描PK_EMP將得到的結果集返回給父步驟2
               步驟2根據上一子步驟3得到的rowid訪問表EMP并將結果集返回給父步驟1
               對于步驟2檢索到的每一行數據,步驟1會將deptno傳遞給步驟5
               步驟5根據得到的deptno執行索引唯一掃描并將結果集返回給步驟4
               步驟4根據步驟5得到的rowid 訪問表dept,并將結果集返回給父步驟1
               對于步驟3中剩余的行依次按上述方式將所有結果集返回給步驟1
               步驟1將獲得的最終結果集返回給步驟0,SQL完成查詢
     
          根據查詢返回的結果來構建執行計劃樹
               從ID為1的列開始,作為根節點
               尋找所有父ID為1的所有子ID,如本例為2和4,將其納入樹中
               分別尋找以2和4為父ID的所有子ID,將其納入樹中
               如此循環直到所有的ID沒有父ID
                  ---------------
                  NESTED LOOP (1)
                  ---------------
                   -        -
                 -           -  
                -              -
           ---------        ----------
           EMP (2)           DEPT(4)
           ---------        ----------
               -                -
              -                  -
       ---------              ----------
       PK_EMP(3)              PK_DEPT(5)    
       ---------             ----------
     5.通過Oracle 自帶的SQL語句執行計劃
      可以通過Oracle提供的SQl語句來獲得當前會話最后一條SQL語句的執行計劃
       utlxpls.sql   -->用于查看串行執行計劃
       utlxplp.sql   -->用于查看并行執行計劃
     
    scott@ORCL> @?/rdbms/admin/utlxpls.sql    --獲得當前session plan_table 最后一條SQL語句的執行計劃                      
                                                                                                                           
    PLAN_TABLE_OUTPUT                                                                                                     
    --------------------------------------------------------------------------------------------------                    
    Plan hash value: 2385808155                                                                                           
                                                                                                                           
    ----------------------------------------------------------------------------------------                              
    | Id  | Operation                    | Name    | Rows  | Bytes | Cost (%CPU)| Time     |                               
    ----------------------------------------------------------------------------------------                              
    |   0 | SELECT STATEMENT             |         |     1 |    28 |     2   (0)| 00:00:01 |                               
    |   1 |  NESTED LOOPS                |         |     1 |    28 |     2   (0)| 00:00:01 |                              
    |*  2 |   TABLE ACCESS BY INDEX ROWID| EMP     |     1 |    14 |     1   (0)| 00:00:01 |                              
    |*  3 |    INDEX UNIQUE SCAN         | PK_EMP  |     1 |       |     0   (0)| 00:00:01 |                              
    |   4 |   TABLE ACCESS BY INDEX ROWID| DEPT    |     4 |    56 |     1   (0)| 00:00:01 |                              
    |*  5 |    INDEX UNIQUE SCAN         | PK_DEPT |     1 |       |     0   (0)| 00:00:01 |                              
    ----------------------------------------------------------------------------------------                              
                                                                                                                           
    Predicate Information (identified by operation id):                                                                   
    ---------------------------------------------------                                                                    
                                                                                                                          
       2 - filter("EMP"."DEPTNO" IS NOT NULL)                                                                              
       3 - access("EMP"."EMPNO"=7788)                                                                                     
       5 - access("EMP"."DEPTNO"="DEPT"."DEPTNO")                                                                          
                                                                                                                          
    19 rows selected.                                                                                                       
                                                                                                                          
    --加載并行SQL的執行計劃                                                                                               
    scott@ORCL> explain plan for select /*+ parallel(t4,2) */ * from t4;                                                  
                                                                                                                           
    Explained.                                                                                                            
                                                                                                                           
    scott@ORCL> @?/rdbms/admin/utlxplp.sql                                                                                
                                                                                                                           
    PLAN_TABLE_OUTPUT                                                                                                     
    ----------------------------------------------------------------------------------------------------------------      
    Plan hash value: 128826497                                                                                            
                                                                                                                           
    --------------------------------------------------------------------------------------------------------------        
    | Id  | Operation            | Name     | Rows  | Bytes | Cost (%CPU)| Time     |    TQ  |IN-OUT| PQ Distrib |        
    --------------------------------------------------------------------------------------------------------------        
    |   0 | SELECT STATEMENT     |          |   400K|  7817K|   183   (4)| 00:00:03 |        |      |            |        
    |   1 |  PX COORDINATOR      |          |       |       |            |          |        |      |            |        
    |   2 |   PX SEND QC (RANDOM)| :TQ10000 |   400K|  7817K|   183   (4)| 00:00:03 |  Q1,00 | P->S | QC (RAND)  |        
    |   3 |    PX BLOCK ITERATOR |          |   400K|  7817K|   183   (4)| 00:00:03 |  Q1,00 | PCWC |            |        
    |   4 |     TABLE ACCESS FULL| T4       |   400K|  7817K|   183   (4)| 00:00:03 |  Q1,00 | PCWP |            |        
    --------------------------------------------------------------------------------------------------------------        
     
    四、總結:
         1. explain plan并不執行當前的SQL語句,而是根據數據字典中記錄的統計信息獲取最佳的執行計劃并加載到表plan_table。
         2. 由于統計信息,執行環境的變化,explain plan與實際的執行計劃可能會有差異。
         3. 對于運行時將較長的SQL語句,不需要等到結果輸出即可提前獲得該SQL的執行計劃,對于生產環境調試情況會減輕數據庫負荷。
         4. 注意set statement_id標識符區分大小寫

    posted on 2014-05-03 11:44 鴻雁 閱讀(168) 評論(0)  編輯  收藏 所屬分類: 數據庫

    主站蜘蛛池模板: 日韩在线观看免费完整版视频| 国产在线观看xxxx免费| 午夜视频在线观看免费完整版| 亚洲中文字幕无码久久| 日韩高清免费在线观看| 香蕉国产在线观看免费| 亚洲av之男人的天堂网站| 老司机在线免费视频| 亚洲人成网站999久久久综合| 免费国产美女爽到喷出水来视频| 国产男女爽爽爽免费视频| 亚洲ⅴ国产v天堂a无码二区| 成人免费激情视频| 一级成人毛片免费观看| 久久精品国产亚洲AV嫖农村妇女| 免费观看的毛片大全| 美女扒开尿口给男人爽免费视频| 亚洲成色在线综合网站| aa级一级天堂片免费观看| 日本永久免费a∨在线视频| 亚洲av女电影网| 国产小视频免费观看| 久久青草91免费观看| 亚洲av日韩av永久在线观看| 亚洲av无码不卡| 国产免费拔擦拔擦8x| 久久免费国产视频| 精品特级一级毛片免费观看| 亚洲第一福利网站| 国产成人免费全部网站| 人人玩人人添人人澡免费| 亚洲AⅤ男人的天堂在线观看| 亚洲av永久无码精品国产精品| 日韩免费视频播放| 91精品全国免费观看含羞草 | 免费人成大片在线观看播放| 久久亚洲免费视频| 亚洲第一永久AV网站久久精品男人的天堂AV | 亚洲男同gay片| 亚洲天堂视频在线观看| 免费人成在线观看视频播放|