Oracle 执行计划说明

  生成SQL的执行计划是Oracle在对SQL做硬解析时的一个非常重要的步骤,它制定出一个方案告诉Oracle在执行这条SQL时以什么样的方式访问数据:索引还是全表扫描,是Hash Join还是Nested loops Join等。先看一个例子:

-bash-3.00$ sqlplus hr/hr123  #以hr用户登录数据库



SQL> set autotrace traceonly;  --开启autotrace功能

SQL> select

  2     t1.first_name,last_name

  3  from  employees t1, jobs t2

  4  where t1.job_id=t2.job_id;



107 rows selected.





Execution Plan

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

Plan hash value: 1445457117



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

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

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

|   0 | SELECT STATEMENT  |           |   107 |  2568 |     3   (0)| 00:00:01 |

|   1 |  TABLE ACCESS FULL| EMPLOYEES |   107 |  2568 |     3   (0)| 00:00:01 |

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





Statistics

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

          8  recursive calls

          0  db block gets

         17  consistent gets

          0  physical reads

          0  redo size

       3058  bytes sent via SQL*Net to client

        462  bytes received via SQL*Net from client

          9  SQL*Net roundtrips to/from client

          0  sorts (memory)

          0  sorts (disk)

        107  rows processed



SQL> 

执行计划中字段解释:

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

2 Operation: 当前操作的内容。

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

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

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

  Cardinality值表示CBO预期从一个行源(row source)返回的记录数,这个行源可能是一个表,一个索引,也可能是一个子查询。   在Oracle 9i中的执行计划中,Cardinality缩写成Card。 在10g中,Card值被rows替换。

  Cardinality的值对于CBO做出正确的执行计划来说至关重要。 如果CBO获得的Cardinality值不够准确(通常是没有做分析或者分析数据过旧造成),在执行计划成本计算上就会出现偏差,从而导致CBO错误的制定出执行计划。

  在多表关联查询或者SQL中有子查询时,每个关联表或子查询的Cardinality的值对主查询的影响都非常大,甚至可以说,CBO就是依赖于各个关联表或者子查询Cardinality值计算出最后的执行计划。

统计信息说明:

1 db block gets : 从buffer cache中读取的block的数量    

2 consistent gets: 从buffer cache中读取的undo数据的block的数量    

3 physical reads: 从磁盘读取的block的数量    

4 redo size: DML生成的redo的大小    

5 sorts (memory) :在内存执行的排序量    

6 sorts (disk) :在磁盘上执行的排序量 

  Physical Reads通常是我们最关心的,如果这个值很高,说明要从磁盘请求大量的数据到Buffer Cache里,通常意味着系统里存在大量全表扫描的SQL语句,这会影响到数据库的性能,因此尽量避免语句做全表扫描,对于全表扫描的SQL语句,建议增 加相关的索引,优化SQL语句来解决。

用以下语句可以查看数据缓冲区的命中率:

 1 SQL> SELECT name, value FROM v$sysstat WHERE name IN ('db block gets', 'consistent gets','physical reads');

 2 

 3 NAME                                                                  VALUE

 4 ---------------------------------------------------------------- ----------

 5 db block gets                                                        439264

 6 consistent gets                                                      195214

 7 physical reads                                                        10667

 8 

 9 SQL> 

10 

11 --数据缓冲区的使用命中率=1 - ( physical reads / (db block gets + consistent gets) )。

12 

13 SQL> select 1-(10667/(439264+195214)) from dual;

14 

15 1-(10667/(439264+195214))

16 -------------------------

17                .983187754

18 

19 SQL> 

  查询出来的结果Buffer Cache的命中率应该在90%以上,否则需要增加数据缓冲区的大小。

动态分析:

  如果在执行计划中有如下提示:

Note

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

   -dynamic sampling used for the statement

  这提示用户CBO当前使用的技术,需要用户在分析计划时考虑到这些因素。 当出现这个提示,说明当前表使用了动态采样。 我们从而推断这个表可能没有做过分析。

这里会出现两种情况:

  1. 如果表没有做过分析,那么CBO可以通过动态采样的方式来获取分析数据,也可以或者正确的执行计划。
  2. 如果表分析过,但是分析信息过旧,这时CBO就不会在使用动态采样,而是使用这些旧的分析数据,从而可能导致错误的执行计划。

 

 

你可能感兴趣的:(oracle)