在上一个关于 CBO 和索引的条目中,我们看到 CBO 在 IN 列表中选择了 5 个不同的值(表示数据的 5%)的查询如何决定使用 FTS,因为这样做的成本低于使用相应索引的成本。这些成本(使用 I/O 成本计算模型)代表了预期的 I/O 数,而 FTS 执行的 I/O 基本上比指数少。更少的 I/O,更低的成本,因此 FTS 被选为首选访问路径。

但是,默认情况下,CBO 在通过 I/O 成本计算模型确定这些成本时,会做出两个非常重要的假设,这些假设可能不一定是正确的。

假设之一是所有I /O都可能是“物理I/O”,所有这些都需要计算成本并加以考虑。

假设二是所有 I/O 的成本相等,即使通常在 FTS 期间执行的多块 I/O 的大小更大,因此可能比通常与索引访问关联的单个块 I/O 成本更高。

今天,我只关注第二个假设。

现在,在 FTS 操作期间执行和处理来自多块 I/O 的数据时,此类操作通常比在索引范围扫描期间执行的单块 I/O 更耗费资源,因为相关的开销可能会更大,例如必须从磁盘读取更多实际数据, 必须将更多数据传输到SGA中,必须在每个相关块中处理更多数据等

因此,并非所有I / O都是相等的。但是,默认情况下,CBO 会忽略所有这些可能的差异,并将与 FTS(多块)和索引(单个块)关联的所有 I/O 的成本为等效或相同。

现在,在确定指数和富时的实际成本差异时,这似乎并不公平,也确实准确不可取。在确定这些相对成本时,难道不应该考虑单个块 I/O 可能占用较少的资源密集度和较少的处理时间这一事实吗?

输入optimizer_index_cost_adj参数。

此参数的目的只是“调整”与索引相关的相应成本,以便(希望)更准确地反映使用索引和 FTS 之间的相对 I/O 成本。例如,如果与多块 I/O 相比,单个块 I/O 仅占用 1/2 的时间和资源来执行,那么在决定是否使用索引并可能因此将索引相关成本降低 1/2 时,难道不应该反映这些相关的 I/O 成本差异吗?

此参数对 CBO 使用基于索引的访问路径的成本有一个非常简单的影响。它将optimizer_index_cost_adj的值作为百分比,并将与索引相关的范围扫描访问路径的成本调整为仅占总索引成本的相应百分比。默认情况下,它的值为 100,这意味着与多块 I/O 相比,单块 I/O 的 I/O 为 100%,这反过来又意味着与索引相关的 I/O 成本的处理方式与多块 FTS I/O 的成本相同。因此,默认值 100 对使用与索引相关的访问路径的总体成本没有影响。

但是,如果optimizer_index_cost_adj的值仅为(例如)25,则意味着所有单块 I/O 的成本仅为多块 I/O 的 25%,因此与索引相关的范围扫描成本被调整为仅占总索引访问路径成本的 25%。

回到上一个选择FTS的演示,我计算了在检索5%的数据时使用索引的成本:

指数水平 + 表(指数选择性 x 叶块) + ceil(表选择性 x 聚类因子)

2 + 5 x ceil(0.01 x 602) + ceil(0.05 x 854) = 2 + 5 x 7 + 43 = 37 + 43 = 80

使用FTS的成本计算为仅为65。FTS的成本为65,低于指数的成本为80,因此选择了FTS。

这一次,链接的演示在再次运行完全相同的查询之前设置optimizer_index_cost_adj = 25

我们注意到几个关键区别。第一个明显的区别是计划已经改变,CBO现在决定使用该指数。第二个区别是与使用指数有关的相关费用。以前,它被计算为80,但现在它的成本只有20。数学非常简单,因为optimizer_index_cost_adj = 25,我们只需要前面的总数为0.25:

(2 + 5 x 头颈鹿(0.01 x 602) + 头皮(0.05 x 854))x 0.25 = (2 + 5 x 7 + 43) x 0.25 = 80 x 0.25 = 20

另请注意,以前只有索引范围扫描成本部分为 2 + 5 x ceil(0.01 x 602) = 37,但现在也调整为 37 x 0.25,四舍五入为9

基本上,通过将optimizer_index_cost_adj = 25,我们有效地将使用基于索引的执行路径的总体成本从80降低到仅20,仅占之前总索引成本的25%。

FTS的成本保持不变,为65。现在,仅 20 的索引访问路径小于 FTS 替代方案,因此该索引现在由 CBO 选择。

是的,当人们了解CBO如何执行其计算以及将optimizer_index_cost_adj参数设置为非默认值的效果时,所有这些数字和成本都是有意义的。

因此,optimizer_index_cost_adj参数显然会对数据库的行为和后续性能产生非常重大的影响,因为 CBO 将按optimizer_index_cost_adj参数中表示的百分比降低(或可能增加)与索引相关的访问路径的实际成本。它可能会显著增加(或减少)选择索引访问路径而不是 FTS 的可能性。

通常有3种非常不同的方式来设置此参数,我将按优先顺序列出

1)将其任意设置为非常低的数字,以便索引占据至高无上的地位,因为它们的相关成本被CBO调整为如此低的数字,以至于FTS访问路径几乎没有机会被选中(例如,这里有一个建议将其设置为12的神奇值)。通常在任何数据库中都是一件非常糟糕的事情...

2) 将其设置为一个值,DBA 确定该值是与单块 I/O 相关的成本与多块 I/O 相比的近似百分比。选项1)的改进),但我仍然更喜欢下一个选项3)...

3) 将其保留为默认值 100,以便它没有影响,并且 CBO 不会使用它来调整索引访问路径的成本

 

我将在第二部分中解释设置optimizer_index_cost_adj参数的明智方法,以及为什么选项 3 是当前支持的任何 Oracle 版本的首选选项。

 

参考至:​​http://richardfoote.wordpress.com/2009/07/08/the-cbo-and-indexes-optimizer_index_cost_adj-part-i/​

如有错误,欢迎指正