一准备工作
1.1 取tracefile的几种办法(11g):

select tracefile ,s.module from v$process p,v$session s where s.paddr=p.addr and s.username='TEST' and module ='SQL*Plus'
SELECT value FROM v$diag_info  WHERE name='Default Trace File';

2 生成10053

alter session set events '10053 trace name context forever';
exec dbms_system.set_ev(sid,serial#,10053,8,'test');

或者通过sql_Id
execute DBMS_SQLDIAG.DUMP_TRACE(p_sql_id=>'5s4ny8pxtdkyf', p_child_number=>0, p_component=>'Optimizer', p_file_id=>'SQL_TRACE_10053');
3 执行sql,关闭trace

select * from T_KINGDEE_CONSUME_DAY;
alter session set events '10053 trace name context off';

二 解析
oracle成本的计算公式如下:
Cost = (
#SRds sreadtim +
#MRds
mreadtim +
CPUCycles / cpuspeed
) / sreadtime
简化为:
cost=#srds + #mrds * mreadtim/sreadtim + #cpucycles/(cpuspped*sreadtim)
#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周期/秒
数据来源:
来源:
select * from sys.aux_stats$
参数解释
FLAGS:标志
CPUSPEEDNW:非工作量统计模式下CPU主频,直接来自硬件
IOSEEKTIM:IO寻址时间(毫秒),直接来自硬件
IOTFRSPEED:IO传输速率(字节/毫秒)
SREADTIM:读取单个数据块的平均时间
MREADTIM:读取多个数据块的平均时间
CPUSPEED:工作量统计模式下CPU主频,根据当前工作量评估出一个合理值
MBRC:oracle收集完统计信息后评估出的一次多块读可以读几个数据块,不设置值其为8
MAXTHR:最大IO吞吐量(字节/秒)
SLAVETHR:平均IO吞吐量(字节/秒)
查看trace文件部分:


SYSTEM STATISTICS INFORMATION

Using NOWORKLOAD Stats
CPUSPEEDNW: 3074 millions instructions/sec (default is 100)
IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
IOSEEKTIM: 10 milliseconds (default is 10)
MBRC: NO VALUE blocks (default is 8)

MBRC:这里在11g里安装完成后不设置显示为128,但在做10053发现其还是为8;
我这里计算为:
sreadtim=ioseektim+db_block_size/IOTFRSPEED=10+8192/4096=12
mreadtim=ioseektim+mbrc*db_block_size/IOTFRSPEED=10+8*8/4=26
查看trace文件:

BASE STATISTICAL INFORMATION

Table Stats::
Table: T_KINGDEE_CONSUME_DAY Alias: T_KINGDEE_CONSUME_DAY
#Rows: 377547 #Blks: 2656 AvgRowLen: 40.00 ChainCnt: 0.00
Index Stats::
Index: IX_KINGDEE_CONSUME_DAY_N1 Col#: 2
LVLS: 2 #LB: 3743 #DK: 951 LB/K: 3.00 DB/K: 397.00 CLUF: 377547.00
Index: PK_T_KINGDEE_CONSUME_DAY Col#: 1 2
LVLS: 2 #LB: 2228 #DK: 377547 LB/K: 1.00 DB/K: 1.00 CLUF: 2979.00
Access path analysis for T_KINGDEE_CONSUME_DAY

io_cost=#mrds*mreadtim/sreadtime=round(2656/8)*26/12=719

计算cpu_cost

explain plan for select * from T_KINGDEE_CONSUME_DAY;
select * from table(dbms_xplan.display());
select cpu_cost from plan_table; 
  CPU_COST
------
 135954115

cpu_cost=135954115/(3074*12)/1000=3.68
整体cost=io_cost+cpu_cost=719+3.7=722.7
查看trace文件部分:

SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for T_KINGDEE_CONSUME_DAY[T_KINGDEE_CONSUME_DAY]
Table: T_KINGDEE_CONSUME_DAY Alias: T_KINGDEE_CONSUME_DAY
Card: Original: 377547.000000 Rounded: 377547 Computed: 377547.00 Non Adjusted: 377547.00
Access Path: TableScan
Cost: 724.69 Resp: 724.69 Degree: 0
Cost_io: 721.00 Cost_cpu: 135954115
Resp_io: 721.00 Resp_cpu: 135954115
Best:: AccessPath: TableScan
Cost: 724.69 Degree: 1 Resp: 724.69 Card: 377547.00 Bytes: 0

调整mbrc
SQL> alter system set db_file_multiblock_read_count=64 scope=both;
查看trace:

SYSTEM STATISTICS INFORMATION

Using NOWORKLOAD Stats
CPUSPEEDNW: 3074 millions instructions/sec (default is 100)
IOTFRSPEED: 4096 bytes per millisecond (default is 4096)
IOSEEKTIM: 10 milliseconds (default is 10)
MBRC: NO VALUE blocks (default is 64)

再次计算成本:

sreadtim=ioseektim+db_block_size/IOTFRSPEED=10+8192/4096=12
mreadtim=ioseektim+dbfilemultiblockreadcount * dbblocksize/IOTFRSPEED=10+64 * 8/4=138
io_cost=#mrds*mreadtim/sreadtime=round(2656/64,2)*138/12=477.25
cpu cost未变;
cost=io_cost+cpu_cost=3.68+477.25=480.93
没调整db_file_multiblock_read_count之前为721,调整后下降很多;
查看10053结果:

Access path analysis for T_KINGDEE_CONSUME_DAY


SINGLE TABLE ACCESS PATH
Single Table Cardinality Estimation for T_KINGDEE_CONSUME_DAY[T_KINGDEE_CONSUME_DAY]
Table: T_KINGDEE_CONSUME_DAY Alias: T_KINGDEE_CONSUME_DAY
Card: Original: 377547.000000 Rounded: 377547 Computed: 377547.00 Non Adjusted: 377547.00
Access Path: TableScan
Cost: 482.69 Resp: 482.69 Degree: 0
Cost_io: 479.00 Cost_cpu: 135954115
Resp_io: 479.00 Resp_cpu: 135954115
Best:: AccessPath: TableScan
Cost: 482.69 Degree: 1 Resp: 482.69 Card: 377547.00 Bytes: 0s

查看explain结果:

PLAN_TABLE_OUTPUT
--------------------------------------------------------------
Plan hash value: 873558201 
----------------------------------------------------------------------
| Id  | Operation                    | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                       |   377K|    14M|   483   (1)| 00:00:06 |
|   1 |  TABLE ACCESS FULL| T_KINGDEE_CONSUME_DAY |   377K|    14M|   483   (1)| 00:00:06 |

发现差一点,483-482,但这里计算的比trace里的差1位,这个差距由参数_table_scan_cost_plus_one控制;
检查参数:

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%';

禁用
alter session set "_table_scan_cost_plus_one"=false;
再次查看执行计划:

Plan hash value: 873558201

-------------------------------------------------------------------------------------------
| Id  | Operation         | Name                  | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT  |                       |   377K|    14M|   482   (1)| 00:00:06 |
|   1 |  TABLE ACCESS FULL| T_KINGDEE_CONSUME_DAY |   377K|    14M|   482   (1)| 00:00:06 |
-------------------------------------------------------------------------------------------

再次调整_table_scan_cost_plus_one为false,后由483降为482;
结论:
db_file_multiblock_read_count这参数会影响你cost(%cpu)的整个结果;