优化器生成正确执行计划的前提条件是要有正确的统计信息,不准确的统计信息往往会导致错误的执行计划。当通过SQL和基数推断出的执行计划和实际执行计划不同时,就可以借助10053事件。10053事件是用来诊断优化器如何估算成本和选择执行计划的,用它产生的trace文件提供了Oracle如何选择执行计划,为什么会得到这样的执行计划信息。和10046事件类似,它主要用于特殊情况下的分析和诊断。

1、测试环境:
SQL> select * from v$version;
BANNER
----------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production

2、建立测试对象
SQL> create table tabtemp as select * from dba_objects where object_id is not null;
Table created.

SQL> select count(object_id) from tabtemp;
COUNT(OBJECT_ID)
----------------
           72764

测试表object_id列的数值分布:
SQL> select count(distinct object_id) from tabtemp;
COUNT(DISTINCTOBJECT_ID)
------------------------
                   72764
建立索引:
SQL> create index idx_tabtemp_id on tabtemp(object_id);

3、生成10053事件
统计表及索引信息:
SQL> exec dbms_stats.gather_table_stats(user,'TABTEMP',cascade=>true);

查看执行计划:
SQL> alter session set tracefile_identifier='plan';
SQL> set autotrace trace exp;
SQL> alter session set events '10053 trace name context forever,level 1';

SQL> select * from tabtemp where object_id=3;
Execution Plan
----------------------------------------------------------
Plan hash value: 2221486709
--------------------------------------------------------------------------------------------
| Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                |     1 |    97 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TABTEMP        |     1 |    97 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_TABTEMP_ID |     1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"=3)
由执行计划可知,查询走索引,这是非常高效的查询方式。

更新测试表,将object_id列数值全部设置为3:
SQL> update tabtemp set object_id=3 where object_id!=3;
72763 rows updated.

SQL> commit;
SQL> select count(distinct object_id) from tabtemp;
COUNT(DISTINCTOBJECT_ID)
------------------------
                       1

不收集统计数据,查看执行计划:
SQL> set autotrace trace exp;
SQL> select * from tabtemp where object_id=3;
Execution Plan
----------------------------------------------------------
Plan hash value: 2221486709
-------------------------------------------------------------------------------------------
| Id  | Operation                   | Name           | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                |     1 |    97 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| TABTEMP        |     1 |    97 |     2   (0)| 00:00:01 |
|*  2 |   INDEX RANGE SCAN          | IDX_TABTEMP_ID |     1 |       |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"=3)
由输出结果可知,本次查询沿用原来的执行计划,是错误的执行计划。

重新对更新后的测试对象进行数据分析:
SQL> set autotrace off;
SQL> exec dbms_stats.gather_table_stats(user,'TABTEMP',cascade=>true);

查看收集统计数据后的执行计划:
SQL> set autotrace trace exp;
SQL> select * from tabtemp where object_id=3;
Execution Plan
----------------------------------------------------------
Plan hash value: 3955501171
-----------------------------------------------------------------------------
| Id  | Operation         | Name    | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |         | 72757 |  6749K|   293   (2)| 00:00:04 |
|*  1 |  TABLE ACCESS FULL| TABTEMP | 72757 |  6749K|   293   (2)| 00:00:04 |
-----------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
   1 - filter("OBJECT_ID"=3)

由输出可知,本次查询使用了正确的执行计划。所以,要注意在实际生产环境中对表、索引等进行及时有效的统计数据收集工作,避免因此带来性能问题。

SQL> alter session set events '10053 trace name context off';
SQL> select value from v$diag_info where name='Default Trace File';
VALUE
------------------------------------------------------------------------------
c:\app\administrator\diag\rdbms\orcl11g\orcl11g\trace\orcl11g_ora_5952_plan.trc

4、分析10053事件trace文件中CBO出错的位置
#more  orcl11g_ora_5952_plan.trc
在前面模拟中有如下操作:
SQL> update tabtemp set object_id=3 where object_id!=3;
72763 rows updated.
SQL> commit;
SQL> select count(distinct object_id) from tabtemp;
COUNT(DISTINCTOBJECT_ID)
------------------------
                       1
SQL> select * from tabtemp where object_id=3;  此处没有重新进行统计信息收集,直接发起查询。

查看10053trace文件中相对应的内容:

***************************************
BASE STATISTICAL INFORMATION
***********************
Table Stats::
  Table: TABTEMP  Alias: TABTEMP
    #Rows: 72764  #Blks:  1062  AvgRowLen:  97.00
Index Stats::
  Index: IDX_TABTEMP_ID  Col#: 4
LVLS: 1  #LB: 161  #DK: 72764 LB/K: 1.00  DB/K: 1.00  CLUF: 1102.00
 
Access path analysis for TABTEMP
***************************************
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for TABTEMP[TABTEMP]
  Table: TABTEMP  Alias: TABTEMP
    Card: Original: 72764.000000  Rounded: 1  Computed: 1.00  Non Adjusted: 1.00
  Access Path: TableScan
    Cost:  291.18  Resp: 291.18  Degree: 0
      Cost_io: 289.00  Cost_cpu: 26481829
      Resp_io: 289.00  Resp_cpu: 26481829
  Access Path: index (AllEqRange)
    Index: IDX_TABTEMP_ID
    resc_io: 2.00  resc_cpu: 15723
    ix_sel: 0.000014  ix_sel_with_filters: 0.000014
    Cost: 2.00  Resp: 2.00  Degree: 1
  Best:: AccessPath: IndexRange
  Index: IDX_TABTEMP_ID
         Cost: 2.00  Degree: 1  Resp: 2.00  Card: 1.00  Bytes: 0
***************************************
 
如上述输出trace文件中加粗所示:
#DK: 表示索引中不同的键值数量。此处数值72764错误,在对表进行更新后,索引中只有1个key。
LB/K:表示每个键值对应多少个leaf blocks。此处数值为1错误,应为leaf blocks即#LB的数值。
DB/K:表示每个key对应多少个数据块。此处数值为1错误,应为#Blks的数值。
Rounded:表示关联后将产生多少条数据。此处数值为1错误,应该是测试表的总行数72764。
ix_sel_with_filters 是带有过滤条件的索引选择率,即过滤因子FF,ix_sel_with_filters =1/DK ,本例中DK数值为1,所以ix_sel_with_filters数值近似为1。
Card:即Cardinality,10gr2以后cardinality用rows表示,是oracle自己估算的数值。本例中应为测试表的行数。
 
本例中Index range scan访问方式cost计算公式为:
cost=blevel + FF*leaf_blocks + FF*clustering_factor,由于FF(ix_sel_with_filters)数值出现的巨大差异(错误的数值为0.000014,正确数值近似等于1),导致Index range scan访问方式cost数值出现严重偏差,最终生成了错误的执行计划。

oracle SQL性能分析之10053事件的更多相关文章

  1. Oracle SQL性能优化技巧大总结

    http://wenku.baidu.com/link?url=liS0_3fAyX2uXF5MAEQxMOj3YIY4UCcQM4gPfPzHfFcHBXuJTE8rANrwu6GXwdzbmvdV ...

  2. ORACLE SQL性能优化(全)

    ORACLE SQL性能优化(全) http://wenku.baidu.com/view/b2aaba3887c24028915fc337.html

  3. Oracle SQL 性能优化技巧

    Select语句完整的执行顺序: SQL Select语句完整的执行顺序: 1. from子句组装来自不同数据源的数据: 2.where子句基于指定的条件对记录行进行筛选: 3.group by子句将 ...

  4. Mysql高级操作学习笔记:索引结构、树的区别、索引优缺点、创建索引原则(我们对哪种数据创建索引)、索引分类、Sql性能分析、索引使用、索引失效、索引设计原则

    Mysql高级操作 索引概述: 索引是高效获取数据的数据结构 索引结构: B+Tree() Hash(不支持范围查询,精准匹配效率极高) 树的区别: 二叉树:可能产生不平衡,顺序数据可能会出现链表结构 ...

  5. Oracle 课程八之性能优化之10053事件

    一. 10053事件 当一个SQL出现性能问题的时候,可以使用SQL_TRACE 或者 10046事件来跟踪SQL. 通过生成的trace来了解SQL的执行过程. 我们在查看一条SQL的执行计划的时候 ...

  6. Oracle 性能调优 10053事件

    思维导图 10053事件概述 我们在查看一条SQL语句的执行计划时,只看到了CBO最终告诉我们的执行计划结果,但是我们并不知道CBO为何要这样做. 特别是当执行计划明显失真时,我们特别想搞清楚为什么C ...

  7. (转)【深度长文】循序渐进解读Oracle AWR性能分析报告

    原文:https://dbaplus.cn/news-10-734-1.html https://blog.csdn.net/defonds/article/details/52958303 作者介绍 ...

  8. Oracle SQL性能优化总结

    1. SQL语句执行步骤 语法分析> 语义分析> 视图转换 >表达式转换> 选择优化器 >选择连接方式 >选择连接顺序 >选择数据的搜索路径 >运行“执 ...

  9. Oracle SQL性能优化的40条军规

    1. SQL语句执行步骤 语法分析> 语义分析> 视图转换 >表达式转换> 选择优化器 >选择连接方式 >选择连接顺序 >选择数据的搜索路径 >运行“执 ...

随机推荐

  1. Python 学习笔记4 变量-字符串

    Python中的字符串,我们可以简单的认为是一组用单引号,双引号,三引号包含的一组字符,数字或者特殊字符.在Python3中,所有的字符串都是Unicode字符串. 变量定义 #单引号 string1 ...

  2. day23:类的命名空间和组合

    1,类属性:静态属性,方法:动态属性:双下init方法,每当我们调用类的时候就会自动的触发这个方法,默认传self,在init方法里面可以对self赋值:在类的内部,self就是一个对象,我们自己实例 ...

  3. 爱奇艺直播 - 春晚直播业务API架构

    小结: 1.服务熔断策略 在网关服务中经常会对后端不同api接口做服务聚合,比如A服务 -> B服务 -> C服务 ,如果C服务出现问题,那么在调用C服务之前需要做熔断.而在设计熔断器的时 ...

  4. 学习Makefile

    1> 编译一个文件2> 编译多个文件3> 编译多个目录下的文件4> inclue makefile5> 使用规则1>target:depend[tab]cmddep ...

  5. 使用java操作elasticsearch(1)

    1.安装elasticsearch 这儿用的是5.6.9的版本,下载安装过程较为简单,在官网上下载好后解压到文件夹.需要注意的是在elasticsearch-5.6.9\config下的elastic ...

  6. 数据结构 - 表插入排序 具体解释 及 代码(C++)

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/u012515223/article/details/24323125 表插入排序 具体解释 及 代码 ...

  7. 配置notepad++支持golang开发

    1 下载golang安装包和配置环境变量 到官网下载golang安装包,下载地址:https://golang.org/dl/,我选择的go1.7.windows-amd64.zip. 配置环境变量: ...

  8. 做一个有产品思维的研发:Scrapy安装

    每天10分钟,解决一个研发问题. 如果你想了解我在做什么,请看<做一个有产品思维的研发:课程大纲>传送门:https://www.cnblogs.com/hunttown/p/104909 ...

  9. JavaScript 区分中英文字符的两种方法: 正则和charCodeAt()方法

    正则无疑是最强大的判断各种条件的方法, 最近也在研习它, 虽然枯燥, 但仍有乐趣. 用它来判断一个双字节的中文字符也是轻而易举地. 而判断中文字符,  简单且执行效率高. regExpForm.onb ...

  10. 用php实现斐波那契数列,如: 1, 1, 2, 3, 5, 8, 13, 21, 34。用数组求出第20个数的值。

    <?php //用数组 function fib($n){ $array = array(); $array[0] = 1; $array[1] = 1; for($i=2;$i<$n;$ ...