CBO的相关原理
CBO在oracle7中被引入,基于数据对象的统计信息(包括数据集的行数,唯一值的个数等等)来计算执行计划的执行成本。随着版本的演化,CBO逐渐完善起来,在9i开始使用系统统计信息(system statistics,系统统计信息的出现是为了估算SQL在CPU方面的消耗)。但是CBO仍然存在一些缺陷,通过了解CBO的一些相关原理,其缺陷大家也就很容易理解了,从而也会明白,很多时候CBO所依赖的统计信息都收集的百分之百准确了,还是会选错执行计划的原因。
执行计划的选择
CBO在生成一条执行计划后,会计算其成本;然后和已经生成的执行计划中成本最低的进行比较。这种比较在以下条件满足其一就停止:
1. 所有执行计划都已经被计算过
查询块的join排列数超过了OPTIMIZER_MAX_PERMUTATIONS(10g及以后为_OPTIMIZER_MAX_PERMUTATIONS)参数指定的值。默认是2000.我们可以做个简单的计算,比如下面这个SQL:
![](http://blog.itpub.net/attachment/201603/8/28218939_1457417015z26I.png)
一个查询块中有7张表,这7张表做join可能的顺序有:
1. a1 -> a2 -> a3 -> a4 -> a5 -> a6 -> a7
2. a1 -> a2 -> a3 -> a4 -> a5 -> a7 -> a6
3. a1 -> a2 -> a3 -> a4 -> a6 -> a5 -> a7
......
所有可能的排列数就是7!=5040,远远超过了OPTIMIZER_MAX_PERMUTATIONS的默认值。那么这种情况下,CBO不会把所有可能的join顺序计算一遍。这就有可能错过了成本最低的执行计划。之所以这么设计是防止过多的对执行计划成本的比较导致花费在SQL解析的时间过长。
成本计算的基本概念
1 cardinality(基数)
cardinality指的是一个行源的结果集的行数。比如在下面这个查询中,返回的为emp表的所有行,基数就是表的行数14.
再比如: