最近学习sql调优,研究CBO的内部成本算法。索引范围扫描是经常见到的执行计划之一,知道其算法,对索引范围扫描执行计划出现问题的时候方便找到问题了。
索引范围扫描成本公式:

下面通过实验来验证其是如何算的。
1.数据库版本

2.创建用户,建立测试表,建立索引并收集统计信息

3.查看索引和表相关的统计信息
索引:select leaf_blocks,blevel,clustering_factor from dba_indexes where index_name='IDX_RANGE_ID';

表:select
b.num_rows,
a.num_distinct,
a.num_nulls,
utl_raw.cast_to_number(high_value) high_value,
utl_raw.cast_to_number(low_value) low_value,
(b.num_rows-a.num_nulls) "NUM_ROWS-NUM_NULLS",
utl_raw.cast_to_number(high_value)- utl_raw.cast_to_number(low_value)"HIGH_VALUE-LOW_VALUE"
from dba_tab_col_statistics a, dba_tables b
where a.owner = b.owner
and a.table_name = b.table_name
and a.owner ='TEST'
and a.table_name = upper('IDX_RANGE')
and a.column_name='OBJECT_ID';

4.执行走索引范围扫描执行计划的语句并查看执行计划

5.根据公式,首先计算IO成本
索引访问IO成本
Index Access I/O Cost = LVLS + CEIL(#LB * ix_sel)
=1+CEIL(195*(1000-2)/87987)

表访问IO成本
Table Access I/OCost=CEIL(CLUF * ix_sel_with_filters)
=CEIL(1358*(1000-2)/87987)

6.计算CPU成本
其实在执行计划也看到,没有cpu的消耗


CPU Cost = ROUND(#CPUCycles cpuspeed / 1000 / sreadtim)
=ROUND(543819/3074/1000/10)

7.综上,COST总成本为:4+16+0=20,和执行计划的结果一致
总结:从索引范围扫描成本算法公式看出,其成本主要受表的集群因子和索引的叶子块数影响较大。如果某条语句一直走索引范围扫描,而突然走了其它的执行计划,比如全表扫描,那就从统计信息过旧,表的集群因子和索引的叶子块数来进行考虑优化了。




