以下内容完全拷贝于ITPUT大牛,为方便查找,做下记录。
原文链接:http://www.itpub.net/thread-1766504-1-1.html

由于帖子较长顾分为2段:第一段  《ORACLE 深入解析10053事件(1)》      http://www.itpub.net/thread-1766504-1-1.html
3.通过10053事件分析一个SQL执行计划的产生过程,需要贴出trace中的相关信息和必要的文字说明。
测试
LEO1@LEO1> drop table leo3 purge;                         清理环境
Table dropped.
LEO1@LEO1> drop table leo4 purge;
Table dropped.
LEO1@LEO1> create table leo3 as select * from dba_objects;     创建leo3表
Table created.
LEO1@LEO1> create table leo4 as select * from leo3 where rownum<100;    创建leo4表
Table created.
LEO1@LEO1> select count(*) from leo4;                      这是个小表
  COUNT(*)
----------
        99
LEO1@LEO1> create index idx_leo3 on leo3(object_id);          创建了索引
Index created.
LEO1@LEO1> create index idx_leo4 on leo4(object_id);          同上
Index created.
LEO1@LEO1> begin
     dbms_stats.gather_table_stats(                leo3表做统计分析
          ownname=>'leo1',
          tabname=>'leo3',
          cascade=>true,
          estimate_percent=>null,
          method_opt=>'for all columns size 1');
end;
/
  2    3    4    5    6    7    8    9  
PL/SQL procedure successfully completed.
LEO1@LEO1> begin
     dbms_stats.gather_table_stats(                 leo4表做统计分析
          ownname=>'leo1',
          tabname=>'leo4',
          cascade=>true,
          estimate_percent=>null,
          method_opt=>'for all columns size 1');
end;
/
  2    3    4    5    6    7    8    9  
PL/SQL procedure successfully completed.
LEO1@LEO1> alter session set events '10053 trace name context forever,level 1';     启动10053事件
10053事件有2个level,1和2,1级比2级内容要详细的多
Session altered.
LEO1@LEO1> select count(*) from leo3,leo4 where leo3.object_id=leo4.object_id;    执行SQL
  COUNT(*)
----------
        99
LEO1@LEO1> alter session set events '10053 trace name context off';           关闭10053事件
Session altered.
LEO1@LEO1> select value from v$diag_info where name='Default Trace File';   当前会话写入的trace
VALUE
-----------------------------------------------------------------------------------------
/u01/app/oracle/diag/rdbms/leo1/LEO1/trace/LEO1_ora_22298.trc
下面我们来看看trace文件中相关信息
参数区        包含初始化参数和隐含参数等
******************************************
----- Current SQL Statement for this session (sql_id=fh7dku2xy52rc) -----   这个会话的SQL_ID
select count(*) from leo3,leo4 where leo3.object_id=leo4.object_id
*******************************************
Legend   下面这些缩写都是优化器使用的trace标识
The following abbreviations are used by optimizer trace.
CBQT - cost-based query transformation
JPPD - join predicate push-down
OJPPD - old-style (non-cost-based) JPPD
FPD - filter push-down
PM - predicate move-around
CVM - complex view merging
SPJ - select-project-join
…………….
Compilation Environment Dump
optimizer_mode_hinted               = false
optimizer_features_hinted           = 0.0.0
parallel_execution_enabled          = true
parallel_query_forced_dop           = 0
parallel_dml_forced_dop             = 0
parallel_ddl_forced_degree          = 0
这些都是参数的默认值
……………………………………
***************************************
Column Usage Monitoring is ON: tracking level = 1     标识10053事件用的时level1级别
***************************************
SQL区    SQL查询转换    合并块   计数统计
**************************
Query transformations (QT)
**************************
****************
QUERY BLOCK TEXT           查询块文本,就是执行的哪个SQL语句
****************
select count(*) from leo3,leo4 where leo3.object_id=leo4.object_id
操作系统统计信息区
-----------------------------
SYSTEM STATISTICS INFORMATION
-----------------------------
  Using NOWORKLOAD Stats        基于非工作量统计模式
  CPUSPEEDNW: 2657 millions instructions/sec (default is 100)  非工作量统计模式下CPU主频
  IOTFRSPEED: 4096 bytes per millisecond (default is 4096)     IO传输速率(字节/毫秒)
  IOSEEKTIM: 10 milliseconds (default is 10)                 IO寻址时间(毫秒)
  MBRC: -1 blocks (default is 8)                           一次多块读可以读几个数据块
基本统计信息(对象级别统计信息)  OLAP系统而言拥有对象级别统计信息就已经足够了
***************************************
BASE STATISTICAL INFORMATION        这些统计信息都来自于视图
***********************
Table Stats::  来自user_tables视图
  Table: LEO4  Alias: LEO4
#Rows: 99  #Blks:  5  AvgRowLen:  75.00   
行数      块数      平均行长
Index Stats::  来自user_indexes视图
  Index: IDX_LEO4  Col#: 4
LVLS: 0  #LB: 1  #DK: 99  LB/K: 1.00  DB/K: 1.00  CLUF: 2.00
索引几层 叶子块数 多少个唯一键值 每个键值有多少个叶块 每个键值有多少个数据块 聚簇因子
***********************
Table Stats::
  Table: LEO3  Alias: LEO3
#Rows: 71969  #Blks:  1051  AvgRowLen:  97.00
行数         块数         平均行长
Index Stats::
  Index: IDX_LEO3  Col#: 4
LVLS: 1  #LB: 159  #DK: 71969  LB/K: 1.00  DB/K: 1.00  CLUF: 1078.00
索引几层 叶子块数 多少个唯一键值 每个键值有多少个叶块 每个键值有多少个数据块 聚簇因子
Access path analysis for LEO3    LEO3表访问路径的不同代价
***************************************
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for LEO3[LEO3]  
  Table: LEO3  Alias: LEO3
Card: Original: 71969.000000  Rounded: 71969  Computed: 71969.00  Non Adjusted: 71969.00
     原始行数             近似值         精确值             非修正值
  Access Path: TableScan     全表扫描代价
    Cost:  286.71  Resp: 286.71  Degree: 0    总代价=286.71
      Cost_io: 286.00  Cost_cpu: 22598123     总代价=IO代价+CPU代价
      Resp_io: 286.00  Resp_cpu: 22598123    并行访问代价
  Access Path: index (index (FFS))   索引快速全扫描
    Index: IDX_LEO3
    resc_io: 45.00  resc_cpu: 9768589           串行访问代价=45(因为索引是串行存储的)
ix_sel: 0.000000  ix_sel_with_filters: 1.000000  ix_sel=1/DK=1/71969=0.000013 索引选择率
ix_sel_with_filters带过滤条件索引选择率
  Access Path: index (FFS)
    Cost:  45.31  Resp: 45.31  Degree: 1       索引并行访问代价=45.31>45(串行访问代价)
      Cost_io: 45.00  Cost_cpu: 9768589        所以要选择串行访问
      Resp_io: 45.00  Resp_cpu: 9768589       并行度=1
  Access Path: index (FullScan)     索引全扫描
    Index: IDX_LEO3
    resc_io: 160.00  resc_cpu: 15533230        串行访问代价=160,这个比较高
    ix_sel: 1.000000  ix_sel_with_filters: 1.000000
    Cost: 160.49  Resp: 160.49  Degree: 1       并行度=1
  Best:: AccessPath: IndexFFS
  Index: IDX_LEO3
         Cost: 45.31  Degree: 1  Resp: 45.31  Card: 71969.00  Bytes: 0
###############################################################################
Access path analysis for LEO4      LEO4表访问路径的不同代价
***************************************
SINGLE TABLE ACCESS PATH
  Single Table Cardinality Estimation for LEO4[LEO4]
  Table: LEO4  Alias: LEO4
Card: Original: 99.000000  Rounded: 99  Computed: 99.00  Non Adjusted: 99.00
原始行数              近似值       精确值          非修正值
  Access Path: TableScan     全表扫描代价
    Cost:  3.00  Resp: 3.00  Degree: 0    总代价=3
      Cost_io: 3.00  Cost_cpu: 56397      IO代价+CPU代价
      Resp_io: 3.00  Resp_cpu: 56397     并行访问代价
  Access Path: index (index (FFS))   索引快速全扫描
    Index: IDX_LEO4
    resc_io: 2.00  resc_cpu: 19001        串行访问代价=2
ix_sel: 0.000000  ix_sel_with_filters: 1.000000   ix_sel=1/DK=1/99=0.01 索引选择率
ix_sel_with_filters带过滤条件索引选择率
  Access Path: index (FFS)
    Cost:  2.00  Resp: 2.00  Degree: 1    索引并行访问代价=2,并行度=1
      Cost_io: 2.00  Cost_cpu: 19001
      Resp_io: 2.00  Resp_cpu: 19001
  Access Path: index (FullScan)     索引全扫描
    Index: IDX_LEO4
    resc_io: 1.00  resc_cpu: 26921        串行访问代价=1,这个最低,就是它了
    ix_sel: 1.000000  ix_sel_with_filters: 1.000000
    Cost: 1.00  Resp: 1.00  Degree: 1
  Best:: AccessPath: IndexRange
  Index: IDX_LEO4
         Cost: 1.00  Degree: 1  Resp: 1.00  Card: 99.00  Bytes: 0
关联查询—驱动表的选择
OPTIMIZER STATISTICS AND COMPUTATIONS     优化器的统计和计算
***************************************
GENERAL PLANS                            选择执行计划
***************************************
Considering cardinality-based initial join order.
Permutations for Starting Table :0
Join order[1]:  LEO4[LEO4]#0  LEO3[LEO3]#1    关联的对象
***************
Now joining: LEO3[LEO3]#1  现在要用leo4小表关联leo3大表,leo4做驱动表
***************
NL Join嵌套循环关联      leo4表中有99条,小表为驱动表
驱动表 Outer table: Card: 99.00  Cost: 1.00  Resp: 1.00  Degree: 1  Bytes: 3
Access path analysis for LEO3
  Inner table: LEO3  Alias: LEO3
  Access Path: TableScan    全表扫描-嵌套循环关联COST=28253.17
    NL Join:  Cost: 28253.17  Resp: 28253.17  Degree: 1
      Cost_io: 28183.00  Cost_cpu: 2237241142
      Resp_io: 28183.00  Resp_cpu: 2237241142     并行访问代价
  Access Path: index (index (FFS))  索引快速全扫描
    Index: IDX_LEO3
    resc_io: 43.08  resc_cpu: 9768589              串行访问代价
    ix_sel: 0.000000  ix_sel_with_filters: 1.000000
  Inner table: LEO3  Alias: LEO3
  Access Path: index (FFS)
    NL Join:  Cost: 4296.33  Resp: 4296.33  Degree: 1   并行访问
      Cost_io: 4266.00  Cost_cpu: 967117228
      Resp_io: 4266.00  Resp_cpu: 967117228
  Access Path: index (AllEqJoinGuess)
Index: IDX_LEO3
    resc_io: 1.00  resc_cpu: 8171
    ix_sel: 0.000014  ix_sel_with_filters: 0.000014
    NL Join (ordered): Cost: 100.03  Resp: 100.03  Degree: 1
      Cost_io: 100.00  Cost_cpu: 835894
      Resp_io: 100.00  Resp_cpu: 835894
  Best NL cost: 100.03   leo4为驱动表,小表为驱动表,最后代价100.03
          resc: 100.03  resc_io: 100.00  resc_cpu: 835894    串行方式的代价  IO代价+CPU代价
          resp: 100.03  resp_io: 100.00  resc_cpu: 835894    并行方式的代价
Outer table:  LEO4  Alias: LEO4
SM Join    先排序后合并关联
  SM cost: 268.06       代价268.06
     resc: 268.06 resc_io: 265.00 resc_cpu: 97470464
     resp: 268.06 resp_io: 265.00 resp_cpu: 97470464
HA Join    哈希关联
  HA cost: 47.03        代价47.03,最好是哈希代价最小
     resc: 47.03 resc_io: 46.00 resc_cpu: 32949334
     resp: 47.03 resp_io: 46.00 resp_cpu: 32949334
Best:: JoinMethod: Hash  最后关联方法选择:哈希hash
       Cost: 47.03  Degree: 1  Resp: 47.03  Card: 99.00 Bytes: 8  返回记录数+字节
***************
Now joining: LEO4[LEO4]#0    现在要用leo3大表关联leo4小表,leo3做驱动表
***************
NL Join   嵌套循环关联      leo3表中有71969条,大表为驱动表
  Outer table: Card: 71969.00  Cost: 45.31  Resp: 45.31  Degree: 1  Bytes: 5
Access path analysis for LEO4
  Inner table: LEO4  Alias: LEO4
  Access Path: TableScan
    NL Join:  Cost: 97632.61  Resp: 97632.61  Degree: 1
      Cost_io: 97505.00  Cost_cpu: 4068618676
      Resp_io: 97505.00  Resp_cpu: 4068618676
  Access Path: index (index (FFS))
    Index: IDX_LEO4
    resc_io: 0.27  resc_cpu: 19001
    ix_sel: 0.000000  ix_sel_with_filters: 1.000000
  Inner table: LEO4  Alias: LEO4
  Access Path: index (FFS)
    NL Join:  Cost: 19581.20  Resp: 19581.20  Degree: 1
      Cost_io: 19538.00  Cost_cpu: 1377283224
      Resp_io: 19538.00  Resp_cpu: 1377283224
  Access Path: index (AllEqJoinGuess)
    Index: IDX_LEO4
    resc_io: 0.00  resc_cpu: 1050
    ix_sel: 0.010101  ix_sel_with_filters: 0.010101
    NL Join (ordered): Cost: 47.68  Resp: 47.68  Degree: 1
      Cost_io: 45.00  Cost_cpu: 85336039
Resp_io: 45.00  Resp_cpu: 85336039
  Best NL cost: 47.68    嵌套循环关联最后代价47.68
          resc: 47.68  resc_io: 45.00  resc_cpu: 85336039
          resp: 47.68  resp_io: 45.00  resc_cpu: 85336039
SM Join   先排序后合并关联
  SM cost: 269.06       代价269.06
     resc: 269.06 resc_io: 265.00 resc_cpu: 129384180
     resp: 269.06 resp_io: 265.00 resp_cpu: 129384180
Hash join: Resc: 106.17  Resp: 106.17  [multiMatchCost=0.00]   哈希关联,代价=106.17
Final cost for query block SEL$1 (#0) - All Rows Plan:
  Best join order: 1    最终代价选择47.0334,用leo4小表驱动表
  Cost: 47.0334  Degree: 1  Card: 99.0000  Bytes: 792
  Resc: 47.0334  Resc_io: 46.0000  Resc_cpu: 32949334
  Resp: 47.0334  Resp_io: 46.0000  Resc_cpu: 32949334
SQL执行计划的选择
============
Plan Table
============
------------------------------------------+-----------------------------------+
| Id  | Operation               | Name    | Rows  | Bytes | Cost  | Time      |
------------------------------------------+-----------------------------------+
| 0   | SELECT STATEMENT        |         |       |       |    47 |           |
| 1   |  SORT AGGREGATE        |         |     1 |     8 |       |           |
| 2   |   HASH JOIN             |         |    99 |   792 |    47 |  00:00:01 |
| 3   |    INDEX FULL SCAN       | IDX_LEO4|    99 |   297 |     1 |  00:00:01 |
| 4   |    INDEX FAST FULL SCAN   | IDX_LEO3|   70K |  351K |    45 |  00:00:01 |
------------------------------------------+-----------------------------------+
Predicate Information:
----------------------
2 - access("LEO3"."OBJECT_ID"="LEO4"."OBJECT_ID")
选择的执行计划和上面分析结果是相匹配的
来看看我们真实的执行计划的样子
LEO1@LEO1> set autotrace trace exp
LEO1@LEO1> select count(*) from leo3,leo4 where leo3.object_id=leo4.object_id;
Execution Plan
----------------------------------------------------------
Plan hash value: 172281424
-----------------------------------------------------------------------------------
| Id  | Operation              | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
-----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT       |          |     1 |     8 |    47   (3)| 00:00:01 |
|   1 |  SORT AGGREGATE       |          |     1 |     8 |            |          |
|*  2 |   HASH JOIN            |          |    99 |   792 |    47   (3)| 00:00:01 |
|   3 |    INDEX FULL SCAN      | IDX_LEO4 |    99 |   297 |     1   (0)| 00:00:01 |
|   4 |    INDEX FAST FULL SCAN  | IDX_LEO3 | 71969 |   351K|    45   (0)| 00:00:01 |
-----------------------------------------------------------------------------------
小结:一模一样对吧,这说明我们的优化器在对比完不同代价后选择的执行计划是最优的,如果我们在实际工作中,遇到了执行计划选择错误的情景,我们可以通过10053事件来做详细的分析。
Leonarding
2013.2.24
天津 &winter
分享技术~成就梦想
Blog : www.leonarding.com
由于帖子较长顾分为2段:第二段  《Oracle 10053事件内部原理与测试(2)》      http://www.itpub.net/thread-1766506-1-1.html
新年新说:
新年伊始,2012年过去了,我们又踏上了2013年的,回顾2012我们付出了很多,辛勤和汗水换来了知识和友谊,当我们技术成长的时候我才发现长路漫漫,唯心可敬。一份耕耘一份收获,走技术之路是艰辛的 孤独的 漫长的,在此向刚入门的小伙子们,说一说心得体会。做好心理准备,可能你为了小小的虚荣心,为了生活所迫,才走上此路,但你也要走的洒脱 走的稳健,当你站在第一个里程碑时回顾来时路,你会发现你的收获是值得的,你的付出是有意思的,你才能有继续走下去的勇气。我要感谢 Alantany  tigerfish  海哥  张老师  飚哥  寅总 dingjun  晶晶 童mm 蓓蓓 还有 好多好多 帮助过我的人们,我的成长离不开你们的鼓励。飙完泪之后开始上干货吧:)
      
ORACLE 深入解析10053事件
本次我们主要讲解oracle 10053事件和实验,好多朋友可能对这个事件不是很熟悉,因为在日常运维中用到的不是很多。Oracle 10046和10053 都是非官方trace sql的方法,在官方文档上是找不到相关资料的,但在MOS上可以找到。sql_trace是官方推荐的trace sql的方法,在官方文档上是可以查询出来的。
10053事件:用来描述oracle如何选择执行计划的过程,然后输出到trace文件里,共我们参考,因为我们经常看执行计划怎么执行的消耗了哪些资源,而不是常看执行计划怎么选择出来了的。
10053场景:当SQL语句执行时走的是错误的执行计划,而又找不到原因时,这时请用10053来分析一下原因。
10053特点:
(1)只可以了解oracle执行计划的选择过程
(2)无法获知代价的计算公式,因为这是oracle内部的商业机密,而且每个oracle版本的优化器计算公式都不相同差距还是蛮大的,不同版本的同一个语句的代价也不一样,优化器现在还不是很成熟,还有待完善。
(3)在这个里面我们重点要了解的是“代价”是如何计算出来的,然后我们才能了解执行计划是如何选择的。
(4)在10053中可以了解哪些因素影响sql的执行代价
(5)oracle 8i cost等价IO资源消耗   9i以后cost等价IO+CPU+网络+等待事件+其他代价
一般IO资源的权重比较大 CPU权重较小
10053内容:
参数区:初始化参数,隐含参数,这些参数可以左右oracle工作方式
SQL区:执行的SQL语句,是否使用绑定变量,是否进行了转换操作
系统信息区:操作系统统计信息  cpu主频 CPU执行时间 IO寻址时间 单块读时间 多块读时间
对象统计信息区:
数据访问方式:访问方式不一样计算代价的方法也不一样,全表扫描 走索引 多表关联 代价都不同
关联查询:把每张表都作为驱动表去组合,择优选择“代价”最小的关联方式,与哪个表在前无关系
代价的最后修正:oracle会对选择出来的代价再进行最后的修正,使其更准确一些,更合理一些
选择出最终执行计划:这个过程是非常快速的,毫秒级就搞定啦
实验环境
LEO1@LEO1> select * from v$version;                     这是我的oracle edition
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
1.验证全表扫描的成本计算公式,贴出执行计划和计算公式。
LEO1@LEO1> col sname for a20
LEO1@LEO1> col pname for a20
LEO1@LEO1> col pual1 for a30
LEO1@LEO1> col pual2 for a30
LEO1@LEO1> select * from sys.aux_stats$;    查看操作系统统计信息
SNAME              PNAME                  PVAL1    PVAL2
-------------------- -------------------- ---------- ---------------------------------------------------
SYSSTATS_INFO        STATUS                             COMPLETED
SYSSTATS_INFO        DSTART                             08-15-2009 00:49
SYSSTATS_INFO        DSTOP                              08-15-2009 00:49
SYSSTATS_INFO        FLAGS                         1
SYSSTATS_MAIN        CPUSPEEDNW            2657.0122  
SYSSTATS_MAIN        IOSEEKTIM                    10   
SYSSTATS_MAIN        IOTFRSPEED                 4096
SYSSTATS_MAIN        SREADTIM      
SYSSTATS_MAIN        MREADTIM      
SYSSTATS_MAIN        CPUSPEED      
SYSSTATS_MAIN        MBRC      
SYSSTATS_MAIN        MAXTHR
SYSSTATS_MAIN        SLAVETHR
说明
aux_stats$是sys管理员用户下的一个基表后缀为$,必须写schema才能查询到,所谓的基表就是给动态性能视图提供数据的原始表,由于基表非常重要,oracle规定不允许直接访问和修改基表,如果你比较了解这些那么另说了。这个表中记录了“操作系统统计信息”。Oracle会利用操作系统统计信息来修正执行计划的代价,也就是说这些信息是影响代价计算的因素之一。
注意:如果oracle收集了操作系统统计信息,那么CBO采用工作量统计模式计算代价
      如果oracle没有收集操作系统统计信息,那么CBO采用非工作量统计模式计算代价,看上面MBRC没有参数值就说明还没有收集操作系统统计信息
这两个模式计算代价的公式是不同的。
SNAME:是指操作系统统计信息
PNAME:parameter name 参数名
PVAL1:参数值
PVAL2:参数值
参数解释
FLAGS:标志
CPUSPEEDNW:非工作量统计模式下CPU主频,直接来自硬件
IOSEEKTIM:IO寻址时间(毫秒),直接来自硬件
IOTFRSPEED:IO传输速率(字节/毫秒)
SREADTIM:读取单个数据块的平均时间
MREADTIM:读取多个数据块的平均时间
CPUSPEED:工作量统计模式下CPU主频,根据当前工作量评估出一个合理值
MBRC:oracle收集完统计信息后评估出的一次多块读可以读几个数据块db_file_multiblock_read_count
MAXTHR:最大IO吞吐量(字节/秒)
SLAVETHR:平均IO吞吐量(字节/秒)
后面这6个参数是在oracle收集完统计信息后才能得出的参数值,有什么用呢?我来解释一下下
CBO在计算SQL语句的代价时,需要使用数据库对象例如表 索引 等对象统计数据,还要使用操作系统统计数据例如CPU周期 IO速度 数据块读时间等,选择花费时间最少的执行计划为最佳执行计划。
Oracle使用dbms_stats.gather_system_stats存储过程来收集操作系统统计信息,收集来的数据存放在sys.aux_stats$表中,如果我们做了收集操作那么会有统计数据,如果没有做就没有统计数据,这两种计算代价的方法是不同的,后续会讲。
dbms_stats.gather_system_stats语法
execute  dbms_stats.gather_system_stats(
gathering_mode varchar2 default ‘noworkload’
interval integer default null,
stattab varchar2 default null,
statid varchar2 default null,
statown varchar2 default null);
解释
gathering_mode 参数,默认值“noworkload”,还可以设置为“workload”含义
noworkload:非工作量统计模式,收集上来的数据都是来自硬件
workload:工作量统计模式,收集上来的数据需要在特定的数据库负载间隔内统计出来的,这样的数据才能真实反映出数据库的操作系统参数(需要执行sql测评出来)
interval:可以指定收集统计信息的时间间隔,例如 5 收集5分钟的统计信息
命令:execute dbms_stats.gather_system_stats(‘noworkload’,5);  
START和STOP关键字自己决定何时开始何时结束收集统计信息
命令:execute dbms_stats.gather_system_stats(‘start’);
上下两条指令间隔3分钟执行,然后把这3分钟的统计信息写入到sys.aux_stats$表里面
execute dbms_stats.gather_system_stats(‘stop’);
注意:上面有个MBRC参数我想多聊一下,它是初始化参数db_file_multiblock_read_count的简写中文翻译“一次读多少个数据块or一次多块读可以读几个数据块”,如果收集了统计信息那么CBO会用MBRC计算代价,如果没有收集统计信息CBO会用这个初始化参数db_file_multiblock_read_count计算代价。
LEO1@LEO1> show parameter db_file_multiblock_read_count     这是我机器上参数默认值
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------------------
db_file_multiblock_read_count            integer       79
LEO1@LEO1> show parameter db_block_size                   我们的一个块大小为8k
NAME                                 TYPE        VALUE
------------------------------------ ----------- ---------------------------------------------
db_block_size                           integer      8192
这个参数值并不是无限大的,大多数平台下的oracle都是128。一般oracle block size =8k
128*8=1M,也就是说1M是大多数操作系统一次最大IO的限制,如果还有其他限制要从这1M里面扣除,初始化参数db_file_multiblock_read_count的最大值之所以定为128,也是为了保守策略。
79*8k=632K
测试
LEO1@LEO1> drop table leo1 purge;                      清空环境
Table dropped.
LEO1@LEO1> create table leo1 as select * from dba_objects;   创建leo1表
Table created.
LEO1@LEO1> begin
     dbms_stats.gather_table_stats(                      收集表的统计信息
          ownname=>'leo1',                            用户名
          tabname=>'leo1',                             表名
          cascade=>true,                               级联操作
          estimate_percent=>null,                       全表采样
          method_opt=>'for all columns size 1');   不作直方图分析,减小代价计算的影响
end;
/
  2    3    4    5    6    7    8    9  
PL/SQL procedure successfully completed.
LEO1@LEO1> show parameter db_file_multiblock_read_count      
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_file_multiblock_read_count           integer     79
LEO1@LEO1> alter session set db_file_multiblock_read_count=16;    把多块读参数修改成16方便计算
Session altered.
LEO1@LEO1> show parameter db_file_multiblock_read_count
NAME                                 TYPE        VALUE
------------------------------------ ----------- ------------------------------
db_file_multiblock_read_count           integer     16
LEO1@LEO1> select * from sys.aux_stats$;         没有收集操作系统统计信息
SNAME                PNAME                     PVAL1 PVAL2
-------------------- -------------------- ---------- ------------------------------
SYSSTATS_INFO        STATUS                          COMPLETED
SYSSTATS_INFO        DSTART                          08-15-2009 00:49
SYSSTATS_INFO        DSTOP                           08-15-2009 00:49
SYSSTATS_INFO        FLAGS                         1
SYSSTATS_MAIN        CPUSPEEDNW            2657.0122
SYSSTATS_MAIN        IOSEEKTIM                    10
SYSSTATS_MAIN        IOTFRSPEED                 4096
SYSSTATS_MAIN        SREADTIM
SYSSTATS_MAIN        MREADTIM
SYSSTATS_MAIN        CPUSPEED
SYSSTATS_MAIN        MBRC
SYSSTATS_MAIN        MAXTHR
SYSSTATS_MAIN        SLAVETHR
我们没有收集操作系统统计信息,所以CBO采用了非工作量统计模式(noworkload)来计算代价
LEO1@LEO1> select blocks from user_tables where table_name='LEO1';   LEO1表总数据块为1051
    BLOCKS
------------------
      1051
LEO1@LEO1> set autotrace trace explain
LEO1@LEO1> select * from leo1;
Execution Plan
----------------------------------------------------------
Plan hash value: 2716644435
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 71968 |  6817K|   233   (1)| 00:00:03 |
|   1 |  TABLE ACCESS FULL| LEO1  | 71968 |  6817K|   233   (1)| 00:00:03 |
--------------------------------------------------------------------------
全表扫描的成本等于233,其中CPU代价占整个权重百分比的1%
###################################################################################
成本的计算公式如下:
Cost = (
       #SRds * sreadtim +
       #MRds * mreadtim +
       CPUCycles / cpuspeed
       ) / sreadtime
      
#SRds - number of single block reads    单块读的次数
#MRds - number of multi block reads    多块读的次数
#CPUCyles - number of CPU cycles       一个CPU周期
sreadtim - single block read time       读取单个数据块的平均时间
mreadtim - multi block read time       读取多个数据块的平均时间
cpuspeed - CPU cycles per second     CPU 周期/秒
注意:如果oracle收集了操作系统统计信息,那么CBO采用工作量统计模式计算代价
      如果oracle没有收集操作系统统计信息,那么CBO采用非工作量统计模式计算代价我们现在处于“非工作量统计模式”
#SRds=0,因为是全表扫描,单块读为0,全都使用的是多块读
#MRds= 表的块数/多块读参数=1051/16=65.6875
mreadtim=ioseektim+db_file_multiblock_count*db_block_size/iotftspeed=10+16*8192/4096=42
sreadtim=ioseektim+db_block_size/iotfrspeed=10+8192/4096=12
CPUCycles 等于 PLAN_TABLE里面的CPU_COST
LEO1@LEO1> explain plan for select * from leo1;
Explained.
LEO1@LEO1> select cpu_cost from plan_table;
  CPU_COST
-----------------
  38430873
cpuspeed 等于 CPUSPEEDNW= 2657.0122
COST=65.6875*42/12+38430873/2657.0122/12/1000(毫秒换算成秒)=229.90625+1.20532=231.11157
229.90625 是IO代价
1.20532   是CPU代价
手工计算出来的COST用四舍五入等于232,和我们看到的233有差别,这是由于隐含参数_table_scan_cost_plus_one参数造成的
LEO1@LEO1> conn / as sysdba        切换到sys用户才能查看隐含参数
SYS@LEO1> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ FROM x$ksppi x,x$ksppcv y
  WHERE x.inst_id = USERENV ('Instance')
   AND y.inst_id = USERENV ('Instance')
   AND x.indx = y.indx
   AND x.ksppinm LIKE '%_table_scan_cost_plus_one%';  2    3    4    5  
NAME                     VALUE        DESCRIB
----------------------------------------------------------------------------------------------------------------------------------------------
_table_scan_cost_plus_one    TRUE         bump estimated full table scan and index ffs cost by one
根据该参数的描述,在table full scan和index fast full scan的时候会将cost+1 即 232+1=233
我们把_table_scan_cost_plus_one参数禁用看看cost变化
SYS@LEO1> alter session set "_table_scan_cost_plus_one"=false;    禁用
Session altered.
SYS@LEO1> SELECT x.ksppinm NAME, y.ksppstvl VALUE, x.ksppdesc describ FROM x$ksppi x,x$ksppcv y
  WHERE x.inst_id = USERENV ('Instance')
   AND y.inst_id = USERENV ('Instance')
   AND x.indx = y.indx
   AND x.ksppinm LIKE '%_table_scan_cost_plus_one%';  2    3    4    5    生效
NAME                     VALUE        DESCRIB
----------------------------------------------------------------------------------------------------------------------------------------------
_table_scan_cost_plus_one    FALSE        bump estimated full table scan and index ffs cost by one
SYS@LEO1> select * from leo1.leo1;
Execution Plan
----------------------------------------------------------
Plan hash value: 2716644435
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 71968 |  6817K|   232   (1)| 00:00:03 |
|   1 |  TABLE ACCESS FULL| LEO1  | 71968 |  6817K|   232   (1)| 00:00:03 |
--------------------------------------------------------------------------
这次得到的COST等于232,与计算值正好匹配,这是禁用隐含参数的结果
SYS@LEO1> alter session set db_file_multiblock_read_count=32;   我们修改一下多块读参数
Session altered.
SYS@LEO1> select * from leo1.leo1;
Execution Plan
----------------------------------------------------------
Plan hash value: 2716644435
--------------------------------------------------------------------------
| Id  | Operation         | Name | Rows  | Bytes | Cost (%CPU)| Time     |
--------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |      | 71968 |  6817K|   204   (1)| 00:00:03 |
|   1 |  TABLE ACCESS FULL| LEO1  | 71968 |  6817K|   204   (1)| 00:00:03 |
--------------------------------------------------------------------------
#SRds=0,因为是全表扫描,单块读为0,全都使用的是多块读
#MRds= 表的块数/多块读参数=1051/32=32.84375
mreadtim=ioseektim+db_file_multiblock_count*db_block_size/iotftspeed=10+32*8192/4096=74
sreadtim=ioseektim+db_block_size/iotfrspeed=10+8192/4096=12
CPUCycles=38430873
cpuspeed 等于 CPUSPEEDNW= 2657.0122
COST=32.84375*74/12+38430873/2657.0122/12/1000(毫秒换算成秒)= 202.53645+1.20532=203.74177
四舍五入等于204,与执行计划中COST=204相一致
小结:从实验中可以得出,oracle 11gR2中,全表扫描非工作量统计模式下COST计算公式依然和9i/10g一样,没有变化。同时我们也看到了IO成本占整个代价权重的极大部分,是影响SQL效率的主要因素,需要我们多关注。
2.给出B-tree索引 Unique scan的成本计算公式,贴出执行计划和计算公式。
CBO各种类型成本计算公式如下:
全表扫描
Full table scan cost= HWM/dbf_mbrc
索引唯一扫描
Unique scan cost = blevel +1
索引快速全扫描
Fast Full Scan cost=leaf_blocks/adj_mbrc
只访问索引,不访问原表扫描
Index-only cost = Blevel + effective index selectivity * leaf_blocks
索引范围扫描
Range Cost = Blevel + effectivity index selectivity* leaf_blocks
                           + effective table selectivity * clustering_factor
嵌套循环关联
nested loop join cost =outer access cost + (inner access cost * outer cardinality)
排序合并关联
sort merge join cost = outer access cost + inner access cost + sort costs
哈希关联
hash join cost = (outer access cost * # of hash partitions) + inner access cost
实验
LEO1@LEO1> drop table leo2 purge;                       清理环境
Table dropped.
LEO1@LEO1> create table leo2 as select * from dba_objects;   创建leo2表
Table created.
LEO1@LEO1> create index idx_leo2 on leo2(object_id);        创建idx_leo2
Index created.
LEO1@LEO1> begin
     dbms_stats.gather_table_stats(                      收集表的统计信息
          ownname=>'leo1',                            用户名
          tabname=>'leo2',                             表名
          cascade=>true,                               级联操作
          estimate_percent=>null,                       全表采样
          method_opt=>'for all columns size 1');   不作直方图分析,减小代价计算的影响
end;
/
  2    3    4    5    6    7    8    9  
PL/SQL procedure successfully completed.
必须要做分析,如果表没有分析,下面统计信息就没有了
LEO1@LEO1> select index_name,blevel,leaf_blocks,clustering_factor,num_rows,distinct_keys from dba_indexes where index_name='IDX_LEO2';
INDEX_NAME   BLEVEL LEAF_BLOCKS CLUSTERING_FACTOR   NUM_ROWS DISTINCT_KEYS
------------------------------ ---------- ----------- ----------------- ---------- ----------------------- -----------------
IDX_LEO2      1      159         1076                71968     71968
BLEVEL:索引层数  1表示就1层
LEAF_BLOCKS:索引树的叶子块数  159
CLUSTERING_FACTOR:索引聚簇因子
NUM_ROWS:有索引的行数    71968和数据行数相匹配
DISTINCT_KEYS:不同的索引键值  71968
LEO1@LEO1> select count(*) from leo2;
  COUNT(*)
-----------------
     71968
LEO1@LEO1> select * from leo2 where object_id=10000;
Execution Plan
----------------------------------------------------------
Plan hash value: 2495991774
----------------------------------------------------------------------------------------
| Id  | Operation                   | Name     | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |          |     1 |    97 |     2   (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID | LEO2     |     1 |    97 |     2   (0)| 00:00:01 |
|*  2 |   INDEX UNIQUE SCAN         | IDX_LEO2 |     1 |       |     1   (0)| 00:00:01 |
----------------------------------------------------------------------------------------
COST=2,其中CPU代价=0,等值查询与索引的条数无关,消耗CPU资源可以忽略不计
Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("OBJECT_ID"=10000)
公式
Unique scan cost = blevel +1
INDEX UNIQUE SCAN的COST=1    就是blevel,CBO看看需要递归几层索引,与统计信息中的blevel一致
TABLE ACCESS BY INDEX ROWID的COST=1  通过索引rowid访问表产生的代价
因此最终COST=1+1=2
Leonarding
2013.2.24
天津 &winter
分享技术~成就梦想
Blog : www.leonarding.com

10053 事件详解相关推荐

  1. oracle 10046事件详解

    10046事件详解 一.10046事件概述 10046是一个Oracle的内部事件(event),通过设置这个事件可以得到Oracle内部执行系统解析.调用.等待.绑定变量等详细的trace信息,即帮 ...

  2. JavaScript事件详解-jQuery的事件实现(三)

    正文 本文所涉及到的jQuery版本是3.1.1,可以在压缩包中找到event模块.该篇算是阅读笔记,jQuery代码太长.... Dean Edward的addEvent.js 相对于zepto的e ...

  3. php jquery点击事件,jQuery操作html元素点击事件详解

    这次给大家带来jQuery操作html元素点击事件详解,jQuery操作html元素点击事件的注意事项有哪些,下面就是实战案例,一起来看一下. 移除或禁用html元素的点击事件可以通过css实现也可以 ...

  4. ASP.NET页面事件详解

    ASP.NET页面事件详解 ASP.NET页面事件详解 1.Page_Init()事件 当页面初始化时发生此事件.可以利用Page_Init()将该事件与要在.NET页面上显示控件之前的运行的代码建立 ...

  5. WPF中的鼠标事件详解

    WPF中的鼠标事件详解 Uielement和ContentElement都定义了十个以Mouse开头的事件,8个以PreviewMouse开头的事件,MouseMove,PreviewMouseMov ...

  6. Spring Data JPA 从入门到精通~Auditing及其事件详解

    Auditing 及其事件详解 Auditing 翻译过来是审计和审核,Spring 的优秀之处在于帮我们想到了很多繁琐事情的解决方案,我们在实际的业务系统中,针对一张表的操作大部分是需要记录谁什么时 ...

  7. 移动端开发touchstart,touchmove,touchend事件详解和项目

    移动端开发touchstart,touchmove,touchend事件详解和项目 最近在做移动端的开发,在一个"服务商管理"页面使用到了触摸事件"touchstart& ...

  8. SQL Server 默认跟踪 -- 捕获事件详解

    SQL Server 默认跟踪 -- 捕获事件详解 哪些具体事件默认跟踪文件能够捕获到? --returns full list of events SELECT * FROM sys.trace_e ...

  9. android 拖动 点击事件,Android事件详解——拖放事件DragEvent

    1.Android拖放框架的作用? 利用Android的拖放框架,可以让用户用拖放手势把一个View中的数据移到当前layout内的另一个View中去. 2.拖放框架的内容? 1)拖放事件类 2)拖放 ...

最新文章

  1. 2016年,这50家创业公司将真正改变世界
  2. IOS修改设备用户代理UserAgent
  3. C# 极限压缩 dotnet core 控制台发布文件
  4. php 复制行,phpstorm怎么快速复制当前行?
  5. Nagios监控ActiveMQ插件开发和部署注意事项
  6. 成功修复2G金士顿U盘
  7. Python内置函数ord()与chr()
  8. Go调用zlib实现压缩与解压缩
  9. 新技能 get —— 如何校验 md5(windows)
  10. php 图片保存到本地文件,php 远程图片保存到本地的函数类
  11. node.js源码安装
  12. 计算机在教育中的应用利与弊,多媒体教学的利与弊
  13. activiti7---activiti7整合springboot
  14. android 多语言国家化对照表(超详细)
  15. Vue使用百度分享,组件切换、销毁分享失效的解决办法
  16. 零代码组态搭建的水泥生产工艺流程
  17. tcl/tk 的安装
  18. 网卡无法再次硬改mac_Intel网卡mac无限硬改工具(IntelMacChanger)
  19. 【毕业设计】基于树莓派的指纹识别打卡系统 - 单片机 物联网
  20. php显示汉字,在php中如何显示汉字?

热门文章

  1. NLP(词向量、word2vec和word embedding)
  2. Jquery实现AJAX异步通信
  3. golang获取时间所在周的起止时间
  4. Unity Shader (Wave Trail)波追踪效果(一)
  5. 目标检测——梯度均衡机制GHM(Gradient Harmonized Mechanism)的理解
  6. DeepLab系列总结
  7. 卡尔曼滤波器、扩展卡尔曼滤波器、无向卡尔曼滤波器的详细推导
  8. (排列组合的重复问题)
  9. 九龙证券|券商春季策略扎堆来袭 风格切换成焦点
  10. 机器学习作业-交通流量预测综述