`

DBMS_XPLAN.Display_Cursor 分析[转]

阅读更多

Oracle 10 added the awesome procedure dbms_xplan.display_cursor but unfortunately the documentation of the package is a bit lacking and the options and output can be confusing, so here are few clarifications.

The procedure display_cursor gives the *real* execution plan instead of an estimated execution plan which is a huge relief after “explain plan”, “set autotrace on” and  “dbms_xplan.display” which all output the expected execution plan. Of the the three, “set autotrace on” is the most peculiar as we can actually run the query and yet the output is the expect plan not the actually executed plan. Pheww – what a relief with dbms_xplan.display_cursor.

But, hold on to the seat of your pants, because that’s not all folks. The coolest thing is that display_cursor will output the actual execution statistics for each row source line in the real execution plan. Now that’s cool. But to access these statistics, one has to enable the collection of the statistics.

To use, run a query in SQL*Plus and include the hint

 /*+ gather_plan_statistics */

then,  immediately following the query execution run:

 select * from table(dbms_xplan.display_cursor(null,null,’ALLSTATS’));

Then you will see the following columns in the output (minus the color coding)

A few confusing things about the output. Some of the columns are estimated statistics from the optimizer. Some of the columns are actual statistics from executing the query. And some of the columns are not per row statistics but statistics that include the statistics of the child rows.

The columns E-Rows and A-Rows can be used for Tuning by Cardinality Feedback (TCF). TCF refers to the process of comparing “E-Row” and “A-Rows” to determine whether the optimizer is optimizing correctly. The two columns “E-Rows” and “A-Rows” which represent estimated rows and actual rows can be compared to highlight how close or how far off the optimizers predictions where. If the optimizers predictions are far of, it’s an indication, though not a proof, that the query has been inadequately optimized. To get the optimizer to  create an optimal execution path, one can look for ways of bringing the optimizers estimated statistics in line with the actual statistics. See Tuning by Cardinality feedback by Wolfgang Breitling.

In V$sql_plan_statistics  these “should” be equal

  • cardinality ~= output_rows/starts
  • starts*cardinality ~= output_rows

And in the output above

  • E-Rows=cardinality
  • A-Rows=output_rows

Thus in order to compare E-Rows to A-Rows, we have to multiply E-Rows by starts.

Other display_cursor 3rd argument options

There are other options besides specifying “ALLSTATS” in the display_cursor. Here are a list of the options and the fields they show:

 

 

By default statistics are total for all executions of the cursor but “LAST” can be appended to the 3rd argument to get the stats for the last execution. NOTE:  the last four columns on memory and temp space always show total or last as indicated above. Here is an example of using “LAST”:

select * from table ( dbms_xplan.display_cursor (null,null,’MEMSTATS LAST‘));

Notice that for memory consumption, some of the stats are bytes and some are kilo-bytes.

The above tables are images. The following table is in text for searching and copy/paste.

Arguments giving only optimizer estimates

  Rows Bytes TempSpc  Cost Time
BASIC          
 null    *      *  *
TYPICAL  *  *  *  *  *
SERIAL  *  *    *  *
ALL  *  *     *  *
ADVANCED  *  *    *  *

 Arguments that give actual row source executions statistics (the red asterisks are estimates)

(the following two tables show the same arguments, but are broken in two to fit the width)

  E-Rows starts A-Rows Buffers Reads Writes A-Time
MEMSTATS  *  *  *        *
ALLSTATS  *  *  *  *  *  *  *
RUNSTATS_LAST  *  LAST  LAST  LAST  LAST  LAST  LAST
RUNSTATS_TOT  *   TOT  TOT  TOT  TOT  TOT  TOT
IOSTATS  *  *  *  *  *  *   *

 

  0Mem 1MEM 0/1/M Used-Mem Used-Tmp Max-Tmp
MEMSTATS  *   TOT LAST LAST TOT
ALLSTATS  *  * TOT LAST LAST TOT
RUNSTATS_LAST            
RUNSTATS_TOT            
IOSTATS            

 Arguments for special cases

  TQ IN-OUT PQ Distrib pstart pstop Instance
PARTITION X X X      
PARALLEL       X X  
REMOTE           X

List of arguments for non-statistical output

  predicate info note Query Block Name Column projection info outline bind vars
BASIC            
null X X        
TYPICAL X X        
SERIAL X X        
ALL X X X X    
ADVANCED X X X X X X
PREDICATES X          
NOTE   X        
ALIAS     X      
PROJECTION       X    
OUTLINES         X  
PEEK_BINDS           X

 

Enabling extended rows source execution statistics gathering

There are three ways to gather row source executions stats:

  1.  /*+ gather_plan_statistics */
  2. sql_trace=true;
  3. Statistics_level=all

The first two are cheaper (sets _rowsource_statistics_sampfreq =128 ) but less accurate than the last option which though more accurate can consume signficantly more CPU (_rowsource_statistics_sampfreq =1).

 Manually querying extended row source execution statistics

The data retrieved with display_cursor can be queried directly from

  • v$sql_plan_statistics
  • v$sql_plan_statistics_all

 

desc v$sql_plan_statistics
ADDRESS
HASH_VALUE
SQL_ID
PLAN_HASH_VALUE
CHILD_ADDRESS
CHILD_NUMBER
OPERATION_ID
EXECUTIONS
LAST_STARTS          STARTS
LAST_OUTPUT_ROWS     OUTPUT_ROWS
LAST_CR_BUFFER_GETS  CR_BUFFER_GETS
LAST_CU_BUFFER_GETS  CU_BUFFER_GETS
LAST_DISK_READS      DISK_READS
LAST_DISK_WRITES     DISK_WRITES
LAST_ELAPSED_TIME    ELAPSED_TIME

and

desc v$sql_plan_statistics_all
 ADDRESS
 HASH_VALUE
 SQL_ID      PLAN_HASH_VALUE CHILD_ADDRESS CHILD_NUMBER
 TIMESTAMP
 OPERATION
 OPTIONS
 OBJECT_NODE  OBJECT# OBJECT_OWNER OBJECT_NAME OBJECT_ALIAS OBJECT_TYPE
 OPTIMIZER
 ID PARENT_ID DEPTH POSITION
 SEARCH_COLUMNS
 COST  CARDINALITY  BYTES
 OTHER_TAG
 PARTITION_START PARTITION_STOP PARTITION_ID
 OTHER
 DISTRIBUTION
 CPU_COST  IO_COST  TEMP_SPACE
 ACCESS_PREDICATES
 FILTER_PREDICATES
 PROJECTION
 TIME (seconds estimated by optimizer)
 QBLOCK_NAME
 REMARKS
 OTHER_XML (bind vars and other info)
 EXECUTIONS
 LAST_STARTS           STARTS
 LAST_OUTPUT_ROWS      OUTPUT_ROWS
 LAST_CR_BUFFER_GETS   CR_BUFFER_GETS
 LAST_CU_BUFFER_GETS   CU_BUFFER_GETS
 LAST_DISK_READS       DISK_READS
 LAST_DISK_WRITES      DISK_WRITES
 LAST_ELAPSED_TIME     ELAPSED_TIME (microseconds)
 POLICY
 ESTIMATED_OPTIMAL_SIZE (bytes)
 ESTIMATED_ONEPASS_SIZE (bytes)
 LAST_MEMORY_USED (bytes)
 LAST_EXECUTION (LAST whether work area was optimal, one pass or multi)
 LAST_DEGREE
 TOTAL_EXECUTIONS (number of times work area was active)
 OPTIMAL_EXECUTIONS
 ONEPASS_EXECUTIONS
 MULTIPASSES_EXECUTIONS
 ACTIVE_TIME (centi-seconds, time work area is active)
 MAX_TEMPSEG_SIZE (kb -  mis-documented as bytes, though correctly bytes in v$sql_workarea )
 LAST_TEMPSEG_SIZE (kb - "" , see  http://www.antognini.ch/2009/05/wrong-information-about-temporary-space-usage/ ) )

so you can write a query to get the data directly such as

col operation for a45
SELECT
      LPAD(' ',depth)||P.OPERATION||'_'||P.OPTIONS||' '||P.OBJECT_NAME  operation
    , last_starts * cardinality e_rows_x_starts
    , last_output_rows  a_rows
    , LAST_CR_BUFFER_GETS bgets
    , LAST_DISK_READS     pread
    , LAST_DISK_WRITES    pwrites
    , LAST_ELAPSED_TIME   elapsed
    , LAST_MEMORY_USED
    , LAST_TEMPSEG_SIZE
    , LAST_EXECUTION
  FROM
       V$SQL_PLAN_statistics_all P
  WHERE
        sql_id='&sql_id'
  order by child_number,id
/

which makes the comparison between estimate and actual easier because I can include starts*cardinality to get the e-rows_x_starts which I can compare directly to a-rows, ie output_rows.

Putting it all together

We can take the TCF ideas farther by putting them together in a query such that the output is easier to  read:

col cn format 99
col ratio format 99
col ratio1 format A6
--set pagesize 1000
set linesize 140
break on sql_id on cn
col lio_rw format 999
col "operation" format a60
col a_rows for 999,999,999
col e_rows for 999,999,999
col elapsed for 999,999,999

Def v_sql_id=&SQL_ID

select
       -- sql_id,
       --hv,
       childn                                         cn,
       --ptime, stime,
       case when stime - nvl(ptime ,0) > 0 then
          stime - nvl(ptime ,0)
        else 0 end as elapsed,
       nvl(trunc((lio-nvl(plio,0))/nullif(a_rows,0)),0) lio_ratio,
       --id,
       --parent_id,
       --starts,
       --nvl(ratio,0)                                    TCF_ratio,
       ' '||case when ratio > 0 then
                rpad('-',ratio,'-')
             else
               rpad('+',ratio*-1 ,'+')
       end as                                           TCF_GRAPH,
       starts*cardinality                              e_rows,
                                                       a_rows,
       --nvl(lio,0) lio, nvl(plio,0)                      parent_lio,
                                                         "operation"
from (
  SELECT
      stats.LAST_ELAPSED_TIME                             stime,
      p.elapsed                                  ptime,
      stats.sql_id                                        sql_id
    , stats.HASH_VALUE                                    hv
    , stats.CHILD_NUMBER                                  childn
    , to_char(stats.id,'990')
      ||decode(stats.access_predicates,null,null,'A')
      ||decode(stats.filter_predicates,null,null,'F')     id
    , stats.parent_id
    , stats.CARDINALITY                                    cardinality
    , LPAD(' ',depth)||stats.OPERATION||' '||
      stats.OPTIONS||' '||
      stats.OBJECT_NAME||
      DECODE(stats.PARTITION_START,NULL,' ',':')||
      TRANSLATE(stats.PARTITION_START,'(NRUMBE','(NR')||
      DECODE(stats.PARTITION_STOP,NULL,' ','-')||
      TRANSLATE(stats.PARTITION_STOP,'(NRUMBE','(NR')      "operation",
      stats.last_starts                                     starts,
      stats.last_output_rows                                a_rows,
      (stats.last_cu_buffer_gets+stats.last_cr_buffer_gets) lio,
      p.lio                                                 plio,
      trunc(log(10,nullif
         (stats.last_starts*stats.cardinality/
          nullif(stats.last_output_rows,0),0)))             ratio
  FROM
       v$sql_plan_statistics_all stats
       , (select sum(last_cu_buffer_gets + last_cr_buffer_gets) lio,
                 sum(LAST_ELAPSED_TIME) elapsed,
                 child_number,
                 parent_id,
                 sql_id
         from v$sql_plan_statistics_all
         group by child_number,sql_id, parent_id) p
  WHERE
    stats.sql_id='&v_sql_id'  and
    p.sql_id(+) = stats.sql_id and
    p.child_number(+) = stats.child_number and
    p.parent_id(+)=stats.id
)
order by sql_id, childn , id
/

which gives output like

    Enter value for sql_id: g2w9n4gksyys6
    old  59:     stats.sql_id='&v_sql_id'  and
    new  59:     stats.sql_id='g2w9n4gksyys6'  and

     CN   ELAPSED    LIO_RATIO TCF_GRAPH   E_ROWS       A_ROWS operation
    --- ------------ --------- ------ ------------ ------------ ------------------------------------------------------------
      0            0         0                                1 SELECT STATEMENT
           5,720,456         0                   1            1  HASH GROUP BY
              29,711         0                            1,909   NESTED LOOPS
                   0         0  +++              1        1,909    NESTED LOOPS
           1,969,304         0  +++              1        1,909     NESTED LOOPS
                   0         0  +++              1        2,027      NESTED LOOPS
           7,939,649         0  +++              1        1,656       NESTED LOOPS
             716,054         0  +++              1        1,657        NESTED LOOPS
             270,201         0  ++              39       23,171         HASH JOIN
                  23         0                   5            1          JOIN FILTER CREATE :BF0000
                  31         1                   5            1           TABLE ACCESS BY INDEX ROWID PS_PAY_CALENDAR
                  14         2                   5            1            INDEX RANGE SCAN PS0PAY_CALENDAR
             141,467         0              18,503       23,171          VIEW  VW_SQ_1
           3,032,120         0              18,503       23,171           HASH GROUP BY
             152,564         0             163,420       33,020            JOIN FILTER USE :BF0000
             407,746         0             163,420       33,020             MERGE JOIN
                  55         0                   5            1              SORT JOIN
                  12         2                   5            1               INDEX RANGE SCAN PS0PAY_CALENDAR
              79,435         0              40,000       33,020              SORT JOIN
             119,852         0              40,000       40,000               INDEX FAST FULL SCAN WB_JOB
           2,959,031        13  -           23,171        1,657         TABLE ACCESS BY INDEX ROWID WB_JOB
             944,887         1              23,171       23,174          INDEX RANGE SCAN WB_JOB
             102,650         0               1,657        1,656        VIEW PUSHED PREDICATE  VW_SQ_2
              73,769         0               1,657        1,657         SORT AGGREGATE
              25,617         0               1,657        1,657          FIRST ROW
             225,497         1               1,657        1,657           INDEX RANGE SCAN (MIN/MAX) WB_JOB
             357,872         0               3,312        2,027       TABLE ACCESS BY INDEX ROWID WB_RETROPAY_EARNS
           3,655,774         1               3,312        2,027        INDEX RANGE SCAN WB_RETROPAY_EARNS_IDX1
             199,884         0               2,027        1,909      TABLE ACCESS BY INDEX ROWID PS_RETROPAY_RQST
             317,793         1               2,027        1,909       INDEX RANGE SCAN PS_RETROPAY_RQST
              71,534         0               1,909        1,909     INDEX RANGE SCAN PS#RETROPAYPGM_TBL
              18,396         0               1,909        1,909    TABLE ACCESS BY INDEX ROWID PS_RETROPAYPGM_TBL

The 3 important parts of this query are

  • Elapsed is per row source, not cumulative of it’s children
  • LIO_RATIO
  • TCP_GRAPH

Elapsed time format has a huge drawback in the display_cursor output as each lines elapsed time includes the elapsed time of all the children which makes an execution plan difficult to scan and see where the time is being spent. In the above output the elapsed time represents the elapsed time of each row source line.

LIO_RATIO shows the number of buffers accessed per row returned. Ideally 1 buffer or less is accessed per row returned. When the number of buffers per row becomes large, it’s a good indication that there is a more optimal method to get the rows.  The I/O stats include the stats of the child row source, so the query has to get the I/O from the childern and subtract from the parent, making the query a bit more complex.

TCP_GRAPH graphically shows the ratio of estimated rows to actual rows. The estimated rows used is cardinality* starts, not just cardinality. This value can be compared directly to actual_rows and the difference in order of magnitude is shown. Each ‘+’ represents and order of magnitude larger and each “-” represents an order of magnitude smaller. The more orders of magnitude, either way, the more the optimizers calculations are off and thus like more pointing to a possible plan that is suboptimal.

In the above output there   are 5 lines where the optimizer only expect 1 row and the actual results were over 1000, ie 3 orders of magnitude difference. These are the three lines with “+++”
There is one line with “-” where actual was an order of magnitude smaller. On that same line we see it’s one of the slower lines almost 3 seconds and that the were 13 lio’s per row returned, which is sign of inefficiency.

 

 

 

 

http://dboptimizer.com/2011/09/20/display_cursor/

  • 大小: 51.2 KB
  • 大小: 32.5 KB
分享到:
评论

相关推荐

    Re-post: DBMS_XPLAN : Display Oracle Execution Plans

    3. `xplan.display_cursor.sql` - 这个文件可能用于显示共享游标(也称为SQL语句的软解析结果)的执行计划,有助于了解当前会话中的SQL性能。 4. `xplan.display.sql` - 这可能是通用的DBMS_XPLAN显示函数的调用...

    Oracle中使用DBMS_XPLAN处理执行计划详解

    DBMS_XPLAN是Oracle提供的一个用于查看SQL计划,包括执行计划和解释计划的包;在以前查看SQL执行计划的时候,我都是使用set autotrace命令,不过现在看来,DBMS_XPLAN包给出了更加简化的获取和显示计划的方式。 这5...

    获取SQL语句的执行计划v1

    本文档详细介绍了几种不同的方法来获取SQL语句的执行计划,包括使用autotrace、EXPLAIN PLAN以及DBMS_XPLAN.DISPLAY_CURSOR等。 #### 方法1:使用autotrace查看执行计划 **配置使用autotrace** 为了能够使用...

    Oracle运维最佳实践-下.pdf 带书签

    - 使用`DBMS_XPLAN.DISPLAY_CURSOR`显示执行计划,查找`dynamic sampling`关键字。 - 使用`DBMS_STATS.SET_DYNAMIC_SAMPLING`设置动态采样的级别。 - **2.1.12 Oracle AIO(异步IO)** - 异步IO是一种高级技术,...

    绑定执行计划.txt

    这条SQL命令使用`dbms_xplan.display_cursor`过程来显示指定SQL_ID(`dw8z3gz4hj1d1`)的执行计划。参数`ADVANCED`表示以高级模式显示执行计划,包括更多细节。 2. **获取历史执行计划** ```sql select distinct ...

    oracle 性能优化

    - 使用`EXPLAIN PLAN FOR`、`DBMS_XPLAN.DISPLAY`和`DBMS_XPLAN.DISPLAY_CURSOR`等工具来查看和理解SQL的执行计划,这有助于识别可能的性能瓶颈,如全表扫描、排序操作、连接方法等。 3. **SQL Trace与TKPROF**: ...

    Oralce 19c执行计划调优学习笔记

    Oralce 19c执行计划调优学习笔记 1_执行计划.pdf 2_explain plan for.pdf 3_dbms_xplan.display_cursor.pdf 4_执行计划顺序.pdf 5_直方图.pdf

    为快捷显示Oracle执行计划创建存储过程

    这个存储过程可以帮助我们省去手动输入`EXPLAIN PLAN FOR`和`DBMS_XPLAN.DISPLAY()`等命令的步骤,使得分析执行计划的过程更加便捷。以下是创建这样一个存储过程的详细步骤和相关知识点: 首先,创建存储过程的代码...

    Oracle中获取执行计划的几种方法分析

    通过查询动态性能视图,如`V$SESSION`和`V$SQL`,可以找到SQL语句的游标信息,然后使用`DBMS_XPLAN.DISPLAY_CURSOR`函数来显示对应的执行计划。这种方法可以获取到最新的执行计划信息。 3. 查询历史执行计划(DBMS_...

    《Pro Oracle SQL》Chapter10 -- 10.2 Optimizing SQL -10.2.1Testing Execution Plans

    使用`DBMS_XPLAN.DISPLAY`或`DBMS_XPLAN.DISPLAY_CURSOR`函数,可以获取带有格式化的执行计划和额外的统计信息。 3. **执行计划的分析** - **操作符**:执行计划由一系列操作符组成,如TABLE ACCESS(表访问)、...

    Oracle面试题

    - 使用 `EXPLAIN PLAN FOR`: 配合 `DBMS_XPLAN.DISPLAY_CURSOR` 来获取执行计划。 - 使用 `DBMS_SYSTEM.SET_SQL_TRACE_IN_SESSION`: 同样会将 SQL 的执行情况记录到追踪文件中。 **3. 如何使用 CBO, CBO 与 RULE 的...

    oracle的索引学习

    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR); ``` 或者使用Autotrace的`TRACEONLY`和`EXPLAIN`选项: ```sql SET AUTOTRACE TRACEONLY EXPLAIN SELECT * FROM EMP; ``` 了解并熟练运用这些工具,可以帮助我们...

    BLOG_【故障处理】Oracle_lhr_队列等待之TX - row lock contention

    - 使用`DBMS_XPLAN.DISPLAY_CURSOR`查看执行计划。 2. **调整事务设计**: - 尽量减少事务的执行时间,避免长时间持有锁。 - 在可能的情况下,采用乐观锁定代替悲观锁定。 3. **利用ADDM(Automatic Database ...

    Oracle并行执行

    4. **`DBMS_XPLAN.DISPLAY_CURSOR`**:可以查看查询计划,了解并行执行的具体细节。 #### 七、并行OLAP系统 在OLAP(联机分析处理)系统中,Oracle并行执行尤为重要。OLAP系统通常需要处理大量的数据,并且经常...

    Oracle sql文总结(case when,查看执行计画,文本操作,查看锁表及解锁,游标)

    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); ``` 这可以帮助优化查询性能,了解数据库如何处理查询,包括使用的索引、连接方法等。 3. **文本操作**: Oracle提供了一系列函数来处理字符串,如`SUBSTR`用于提取...

    oracle获取执行计划全部方法

    使用 `SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY_CURSOR(NULL, NULL, 'ALLSTATS LAST'));` 查看包含详细统计信息的执行计划。 - **其他技巧**: - 使用 `/*+ GATHER_PLAN_STATISTICS */` 注释可以在不设置 `...

    Oracle常用命令全集

    `EXPLAIN PLAN`用于分析SQL执行计划,`DBMS_XPLAN.DISPLAY_CURSOR`查看执行计划的详细信息,`V$SESSION_WAIT`和`V$SYSTEM_EVENT`视图用于监控系统等待事件。 14. **权限管理**: `GRANT`和`REVOKE`用于赋予和撤销...

    SQL Tuning.ppt

    在Oracle 10g中,可以使用`dbms_xplan.display_cursor()`来获取实际执行的计划,这是比早期版本更可靠的方法,因为它直接来源于`V$sql_plan`视图。然而,在9i及更早版本中,可能需要依赖其他如SQL_TRACE和AUTOTRACE...

    SQL.rar_oracle_oracle里的常用命令_shelfcro

    - `EXPLAIN PLAN`或`DBMS_XPLAN.DISPLAY`:用于分析查询计划和索引使用。 10. **视图(VIEW)** - 视图是虚拟表,基于一个或多个表的查询结果,如`CREATE VIEW view_name AS SELECT ...;`。 11. **存储过程和...

Global site tag (gtag.js) - Google Analytics