Analyze SQL Performance Using Oracle Execution Plans

Execution plans can be used to analyze the performance of SQL

 

1. How to view the execution plan

1. Set autotrace

    set autotrace off : This is the default value, which turns off autotrace

    set autotrace on explain : show only the execution plan

    set autotrace on statistics : only display execution statistics

    set autotrace on : display both the execution plan and execution statistics

    set autotrace traceonly : similar to on, but does not display the execution result of the statement

 

    Example:

        set autotrace on;

        select 1 from dual;

 

    Note: If the following error message appears when executing set autotrace:

             SP2-0618: Cannot find the Session Identifier.  Check PLUSTRACE role is enabled

             SP2-0611: Error enabling STATISTICS report 

             You can try the following solutions:

             conn / as sysdba;

             Execute @$ORACLE_HOME/RDBMS/ADMIN/utlxplan.sql, or execute the contents of the $ORACLE_HOM\product\11.2.0\dbhome_1\RDBMS\ADMIN\utlxplan.sql file.

             Execute @$ORACLE_HOME/sqlplus/admin/plustrce.sql, or execute the contents of the $ORACLE_HOM\product\11.2.0\dbhome_1\sqlplus\admin\plustrce.sql file.

             grant plustrace to public;

 

2. Using SQL

    Execute: explain plan for <sql statement>

    查看:SELECT plan_table_output FROM TABLE(DBMS_XPLAN.DISPLAY('PLAN_TABLE'));

             或 select * from table(dbms_xplan.display);

 

    Example:

        explain plan for select 1 from dual;

        select * from table(dbms_xplan.display);

 

3. Use PL/SQL Developer, Toad and other tools

    In PL/SQL Developer, select the SQL statement, and then click the menu "Tools" - "Explain Plan" or press the shortcut key F5.

 

2. Execution plan result information description

 

    The above execution plan example may output the following information after running, and the following information will be further explained

 

PLAN_TABLE_OUTPUT

--------------------------------------------------------------------------------

Plan hash value: 1388734953

--------------------------------------------------------------------------------

| Id  | Operation                | Name | Rows  | Cost (%CPU)| Time     |

--------------------------------------------------------------------------------

|   0 | SELECT STATEMENT |           |     1    |     2   (0)      | 00:00:01 |

|   1 |  FAST DUAL              |           |     1    |     2   (0)      | 00:00:01 |

--------------------------------------------------------------------------------

 

1. 执行计划中字段的说明

    Id: 一个序号,但不是执行的先后顺序。执行的先后根据缩进来判断。

    Operation: 当前操作的内容。

    Name: 操作的对象名称。

    Rows: 当前操作的基数,Oracle估计当前操作的返回结果集。

    Cost(%CPU): Oracle 计算出来的一个数值(代价),用于说明SQL执行的代价。

    Time: Oracle估计当前操作的时间

 

2. 执行计划中内容的说明

 

    table access full: 全表扫描,对所有表中记录进行扫描。使用多块读操作,一次I/O能读取多块数据块。表字段不涉及索引时往往采用这种方式。

                             较大的表不建议使用全表扫描,除非结果数据超出全表数据总量的10%。

    table access by index rowid: 通过ROWID的表存取,一次I/O只能读取一个数据块。通过rowid读取表字段,rowid可能是索引键值上的rowid。

 

    4种类型的索引扫描(index scan)

    index unique scan: 索引唯一扫描,如果表字段有UNIQUE 或PRIMARY KEY 约束,Oracle实现索引唯一扫描,这种扫描方式条件比较极端,出现比较少。

    index range scan: 索引范围扫描,最常见的索引扫描方式。在非唯一索引上都使用索引范围扫描。

 1 ) 在唯一索引列上使用了以下圈定范围的操作符(> < <> >= <= between等)

        2 ) 在组合索引上,只使用部分列进行查询,导致查询出多行

        3 ) 对非唯一索引列上进行的任何查询

    index full scan:  索引全扫描,这种情况下,是查询的数据都属于索引字段,一般都含有排序操作。

    index fast full scan: 索引快速扫描,如果查询的数据都属于索引字段,并且没有进行排序操作,那么是属于这种情况。条件比较极端,出现比较少。

    

    表之间的连接方式

    nested loops: 嵌套循环,该连接过程就是一个2层嵌套循环,所以外层循环的次数越少越好。

                         如果driving row source(外部表)比较小,并且在inner row source(内部表)上有唯一索引,

                         或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。

    hash join: 哈希连接,在2个较大的row source之间连接时会取得相对较好的效率,在一个row source较小时则能取得更好的效率。

    sort merge join: 排序 - 合并连接,该种排序限制较大,出现比较少

                            内部连接过程:

        1) 首先生成表1需要的数据,然后对这些数据按照连接操作关联列进行排序;

        2) 随后生成表2需要的数据,然后对这些数据按照与表1对应的连接操作关联列进行排序;

        3) 最后两边已排序的行被放在一起执行合并操作,即将2个表按照连接条件连接起来。

 

三、表连接方法

  1. 排序 - - 合并连接(Sort Merge Join, SMJ):

  a) 对于非等值连接,这种连接方式的效率是比较高的。

  b) 如果在关联的列上都有索引,效果更好。

  c) 对于将2个较大的row source做连接,该连接方法比NL连接要好一些。

  d) 但是如果sort merge返回的row source过大,则又会导致使用过多的rowid在表中查询数据时,数据库性能下降,因为过多的I/O.

 

  2. 嵌套循环(Nested Loops, NL):

  a) 如果driving row source(外部表)比较小,并且在inner row source(内部表)上有唯一索引,或有高选择性非唯一索引时,使用这种方法可以得到较好的效率。

  b) NESTED LOOPS有其它连接方法没有的的一个优点是:可以先返回已经连接的行,而不必等待所有的连接操作处理完才返回数据,这可以实现快速的响应时间。

 

  3. 哈希连接(Hash Join, HJ):

  a) 这种方法是在oracle7后来引入的,使用了比较先进的连接理论,一般来说,其效率应该好于其它2种连接,但是这种连接只能用在CBO优化器中,而且需要设置合适的hash_area_size参数,才能取得较好的性能。

  b) 在2个较大的row source之间连接时会取得相对较好的效率,在一个row source较小时则能取得更好的效率。

  c) 只能用于等值连接中

 

 四、执行计划统计信息

1. 统计信息含义

    recursive calls: 递归调用次数; 

    db block gets: 当期操作时从内存读取的当前最新块数据,并不是在一致性读的情况的块数,即通过update/delete/select for update读的块数; 

    consistent gets: 当期操作时在一致性读状态下读取的块数,即通过不带for update的select 读的块数; 

    physical reads: 物理读,Oracle从磁盘读的数据块数量, 其产生的主要原因是:在数据库高速缓存中不存在这些块;全表扫描;磁盘排序。其中逻辑读指的是Oracle从内存读到的数据块数量。一般来说是'consistent gets' + 'db block gets'。当在内存中找不到所需的数据块的话就需要从磁盘中获取,于是就产生了'phsical reads'。 

    redo size: 执行SQL的过程中产生的重做日志; 

    519 bytes sent via SQL*Net to client: 通过网络发送给客户端的数据 

    524 bytes received via SQL*Net from client: 通过网络从客户端接收到的数据 

    SQL*Net roundtrips to/from client:通过网络客户端发送或接收的数量

    sorts (memory): 在内存中发生的排序

    sorts (disk): 在硬盘中发生的排序

    rows processed:处理的行数

 

2. 统计信息示例



 

 

参考资料:

http://www.cnblogs.com/jianggc/articles/2029854.html

http://www.cnblogs.com/fqw1987815/archive/2010/08/18/1802657.html

http://blog.csdn.net/zongrongna/article/details/51580415

http://blog.chinaunix.net/uid-21187846-id-3022916.html

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326561595&siteId=291194637