测试库两张表,数据一致,(表有复合主键a+b),但同样执行delete table from t1/t2 where a='1' and rownum
plan_table_output
-----------------------------------------------------------------------
| id | operation | name | rows | bytes | cost |
-----------------------------------------------------------------------
| 0 | delete statement | | 1000 | 12000 | 3217 |
| 1 | delete | t1 | | | |
|* 2 | count stopkey | | | | |
|* 3 | index range scan | idx_t1 | 420k| 4931k| 3217 |
-----------------------------------------------------------------------
predicate information (identified by operation id):
plan_table_output
--------------------------------------------------------------------------------
2 - filter(rownum3 - access(t1.a='1')
note: cpu costing is off
plan_table_output
--------------------------------------------------------------------
| id | operation | name | rows | bytes | cost |
--------------------------------------------------------------------
| 0 | delete statement | | 1000 | 12000 | 2965 |
| 1 | delete | t2 | | | |
|* 2 | count stopkey | | | | |
|* 3 | index range scan | idx_t2 | 393k| 4607k| 2965 |
--------------------------------------------------------------------
predicate information (identified by operation id):
plan_table_output
--------------------------------------------------------------------------------
2 - filter(rownum3 - access(t2.a='1')
note: cpu costing is off
显然感觉这两个表的实际操作和执行计划不太相符,这时10053事件就起到了作用。
10053介绍:
10053 事件是oracle 提供的用于跟踪sql 语句成本计算的内部事件,它能记载cbo 模式下oracle 优化器如何计算sql 成本,生成相应的执行计划。 用来描述oracle如何选择执行计划的过程,然后输出到trace文件里,因为我们经常看执行计划怎么执行的消耗了哪些资源,而不是常看执行计划怎么选择出来了的。
10053特点:
(1) 只可以了解oracle执行计划的选择过程
(2) 无法获知代价的计算公式,因为这是oracle内部的商业机密,而且每个oracle版本的优化器计算公式都不相同差距还是蛮大的,不同版本的同一个语句的代价也不一样,优化器现在还不是很成熟,还有待完善。
(3) 在这个里面我们重点要了解的是“代价”是如何计算出来的,然后我们才能了解执行计划是如何选择的。
(4) 在10053中可以了解哪些因素影响sql的执行代价
(5) oracle 8i cost等价io资源消耗 9i以后cost等价io+cpu+网络+等待事件+其他代价
t1表的10053事件信息:
***************************************
base statistical information
***********************
table stats table: t1 alias: t1 来自user_tables视图
total :: cdn: 2341358 nblks: 13921 avg_row_len: 40
-- index stats 来自user_indexes视图
index name: idx_starother col#: 2 3
total :: lvls: 2 #lb: 13609 #dk: 2156054 lb/k: 1 db/k: 1 cluf: 165252
_optimizer_percent_parallel = 0
***************************************
single table access path
column: airline_co col#: 2 table: t1 alias: t1
ndv: 7 nulls: 0 dens: 1.4286e-01
no histogram: #bkt: 1 #val: 2
table: starotherprf orig cdn: 2341358 rounded cdn: 334480 cmptd cdn: 334480
access path: tsc resc: 1340 resp: 1340 全表扫描代价(1340),这里tsc我想应该是tablescan的缩写
skip scan: ss-sel 0 andv 308008
ss cost 308008 索引跳跃扫描的代价(1945)
index io scan cost 1945
access path: index (index-only) 索引(范围)扫描代价(1947)
index: idx_t1
table: t1
rsc_cpu: 0 rsc_io: 1947
ix_sel: 1.4286e-01 tb_sel: 1.4286e-01
best_cst: 1340.00 path: 2 degree: 1 最佳代价是1340,即全表扫描
对应的执行计划:
***************************************
general plans
***********************
join order[1]: starotherprf[starotherprf]#0
best so far: table#: 0 cst: 1340 cdn: 334480 bytes: 4348240
final - all rows plan:
join order: 1
cst: 1340 cdn: 334480 rsc: 1340 rsp: 1340 bytes: 4348240
io-rsc: 1340 io-rsp: 1340 cpu-rsc: 0 cpu-rsp: 0
query
explain plan for delete from starotherprf where airline_code = 'us' and rownum plan
cost of plan: 1340
operation...........object name.....options.........id...pid..
delete statement 0
delete starotherprf 1
count stopkey 2 1
table access t1 full 3 2
query
显示用的就是全表扫描
t2表的10053事件信息:
***************************************
single table access path
column: airline_co col#: 1 table: t2 alias: t2
ndv: 19 nulls: 0 dens: 5.2632e-02
no histogram: #bkt: 1 #val: 2
table: castarprf orig cdn: 6665065 rounded cdn: 350793 cmptd cdn: 350793
access path: tsc resc: 4275 resp: 4275 全表扫描代价(4275)
skip scan: ss-sel 0 andv 413617 索引跳跃扫描代价(413617)
ss cost 413617
index io scan cost 1973
access path: index (index-only) 索引(范围)扫描代价(1975)
index: idx_t2
table: t2
rsc_cpu: 0 rsc_io: 1975
ix_sel: 5.2632e-02 tb_sel: 5.2632e-02
best_cst: 1975.00 path: 4 degree: 1 最佳代价是1975,即索引扫描
对应的执行计划:
***************************************
general plans
***********************
join order[1]: castarprf[castarprf]#0
best so far: table#: 0 cst: 1975 cdn: 350793 bytes: 4911102
prefetching is on for idx_castar
final - all rows plan:
join order: 1
cst: 1975 cdn: 350793 rsc: 1975 rsp: 1975 bytes: 4911102
io-rsc: 1975 io-rsp: 1975 cpu-rsc: 0 cpu-rsp: 0
query
explain plan for delete from castarprf where airline_code = 'us' and rownum plan
cost of plan: 1975
operation...........object name.....options.........id...pid..
delete statement 0
delete castarprf 1
count stopkey 2 1
index idx_t2 range scan 3 2
query
显示用的就是索引扫描
现在就可以知道为什么这两张表删除时间不同了,原因就是t1表cbo选择了错误的执行计划,导致全表扫描,因此百万级的数据就会耗费更长的时间。
总结:当感觉sql语句执行时走的是错误的执行计划,而又找不到原因时,这时请用10053来分析一下原因。这就是10053的适用场景。
