我之前讨论过一些基本概念和公式,这些概念和公式涉及 CBO 如何通过 I/O 成本核算模型派生与索引相关的成本核算。是时候查看系统统计信息和 CPU 成本计算模型了,具体涉及索引。

我要说的第一点是,CPU 成本模型比旧的 I/O 成本计算方法有一些重大改进,我强烈建议尽可能采用 CPU 成本模型。我将解释其中一些改进和优势,而不是即将发布的帖子。

I/O 成本核算模型基本上根据物理 I/O 的估计数量来查看特定执行计划的成本。I/O 越少,执行计划的成本越低、效率越高,预期响应时间越快。然而,这种基本的I / O成本计算策略存在许多缺点,因为它不会自动区分与不同类型的I / O相关的成本(例如,在单块和多块读取之间),它不会自动确定多块I / O的典型或平均大小,也不会花费并考虑与可能的CPU资源相关的时间和开销。

CPU 成本模型尝试考虑这些以前的限制。它会自动考虑完成平均单块 I/O 与多块 I/O 的时间之间的差异,自动确定多块 I/O 的平均大小,以便更准确地确定 FTS 中多块 I/O 的可能数量,并自动确定特定任务的预期 CPU 时间。

要使用CBO CPU成本模型,需要收集系统统计信息,以便CBO根据实际的系统硬件特征获得此附加信息(注意:自10g起,隐藏参数_optimizer_cost_model默认为“cpu”,因此默认情况下使用)。您可以使用dbms_stats.collect_system_stats 过程执行此操作。您可以收集“Noworkload”统计信息,其中 Oracle 基本上随机读取数据库数据文件,以确定基本统计信息,例如平均 I/O 寻道时间、平均 I/O 传输速度和 CPU 速度。但是,我宁愿建议收集“工作负载”统计信息,这些统计信息基于硬件的实际工作负载特征,基于收集系统统计信息期间系统上的实际负载(在这种情况下,将忽略 Noworkload 统计信息)。

您可以通过以下两种方式收集工作负载系统统计信息:

dbms_stats.collect_system_stats(“START”)启动系统统计信息收集过程,然后dbms_stats.gather_system_stats(“STOP”)在典型的工作负载时间段内停止收集过程,或者

dbms_stats.gather_system_stats(“间隔”,间隔=> 120) 说收集 120 分钟内的系统工作负载统计信息。

要查看收集的系统统计信息,请查询 SYS。AUX_STATS$.


SQL>从系统选择 pname, pval1.AUX_STATS$
在哪里(“只读”,“只读”,“MBRC”,“CPU速度”);

 



PNAME PVAL1 ------------ ---------- SREADTIIM 5 MREADTIIM 10 CPUSPEED 1745 MBRC 10



 
我现在要关注的四个系统统计信息是:

SREADTIM – 单个块 I/O
MREADTIM 的时间(以毫秒为单位) - 多块 I/O
CPUSPEED 的时间(以毫秒为单位) - 每秒
数百万个 CPU 周期 MBRC – 多块读取操作

期间实际读取的平均块数因此,在上图中,请注意,多块读取的平均时间大约是单个块读取时间的两倍,并且在多块读取操作期间平均读取10个块。这为CBO提供了有关如何现在如何计算成本和比较潜在执行计划的重要信息。


CBO CPU 成本模型基本上通过以下方法查看完成执行计划所需的总时间:

完成所有单块 I/O 活动的总时间 +
完成所有多块 I/O 活动的总时间 +
完成所有 CPU 活动


的总时间 这基本上可以计算如下:

所有单块 I/O 的总和 x 单个块 I/O 的平均等待时间 +
所有多块 I/O 的总和 x 多块 I/O 的平均等待时间 +
所有所需 CPU 周期/每秒

CPU 周期的总和 理论上,这应该提供总响应时间来为执行计划提供服务。但是,为了使 CBO 计算的实际“成本”数字与 I/O 成本模型保持一致,CBO 将此总时间除以单个块 I/O 的平均时间,使得完整公式变为:

(单个块 I/O 的所有单块 I/O 的平均等待时间之和 +
多块 I/O 的所有多块 I/O 的平均等待时间之和 + 多块 I/O 的总和 +
因此,即使使用CPU

成本模型模型,最终的“成本”数字仍然以单个块I /
O的单位表示。这是重要的一点...

那么,CBO如何确定此公式中各种数字的值?正如我们将看到的,CBO 从系统统计信息和前面与 I/O 成本核算模型讨论的成本计算公式中获取所需的信息。

但是,对于与索引相关的访问路径,有一些关于能够简化问题的好消息。

第一个好消息是,从索引访问路径的角度来看,没有多块I / O(除了快速完整索引扫描),因此CPU成本计算公式可以简化索引以删除多块读取组件,只需:

(单个块I / O的所有单块I / O的平均等待时间之和+
所有所需CPU周期/ CPU的总和。每秒周期数)
/
单个块 I/O

的平均等待时间 其次,如果 CPU 组件相对微不足道,则可能不足以计入最终成本。由于较小的索引扫描可能消耗很少的 CPU,这意味着 CPU 组件通常也可以被忽略。这将此类索引扫描的公式简化为:

(单个块 I/O 的所有单块 I/O 的平均等待时间之和)
/
单个块 I/O

的平均等待时间,但是,单个块 I/O 的平均等待时间现在在这个简化的等式中变得多余,从而降低了成本,现在只是:

所有单个块 I/O
的总和 对于那些关注我之前关于 CBO 和 Index 的博客文章的人来说,下一个好消息是,在确定所有预期 I/O 的总和时,以前关于 I/O 成本模型的公式仍然适用。与索引扫描关联的所有单个块 I/O 的总和仍然基本为:

所有单个块 I/O 的总和 = 索引平整 + ceil(索引选择性 x 叶块) + ceil(表选择性 x 聚类因子)
换句话说,对于较小的索引扫描执行计划,CBO 使用 CPU 成本模型计算的成本与 I/O 成本计算模型的成本相同。所以,不,我没有浪费每个人的时间讨论使用较旧的I / O成本模型的各种公式:)

如果我们运行与我之前在关于CBO和Index的初始帖子中运行的演示相同的演示,其中索引访问计划的总成本为18,但这次使用上面列出的系统统计信息:

SQL>更改会话集“_optimizer_cost_model”=CPU;

会话已更改。

SQL>从bowie_stuff2中选择 *,其中 id = 420;

已选择 2000 行。

 

执行计划
———————————————————-
计划哈希值:134336835

——————————————————————————–
|Id|操作|名称|行|字节|成本 (%CPU)|时间|
——————————————————————————-
|0|选择声明 | |2000|36000|18 (0)|00:00:00|
|1|按索引 ROWID 进行表访问|BOWIE_STUFF2 |2000|36000|18 (0)|00:00:00|
|×2|索引范围扫描|BOWIE_STUFF2_I|2000| |9 (0)|00:00:01|
——————————————————————————–

 

我们注意到,在比较使用 IO 成本模型的成本与 CPU 成本计算模型的成本时,索引范围扫描组件的成本在 9 处完全相同,在总执行计划的 18 处完全相同。引入系统统计信息并未更改此特定索引相关执行计划的内容。

这是一个非常普遍的观察结果。由于索引使用单块 I/O,由于 CBO 成本仍作为单个块 I/O 的一个单位,并且由于索引扫描的 CPU 消耗通常微不足道,因此索引访问路径的所产生成本通常与 CPU 成本模型保持不变。

之前,我们研究了更改参数(如optimizer_index_cost_adj)如何影响与索引相关的执行计划的成本核算,以便在索引和 FTS 执行计划之间创建一个公平的竞争环境。

关于系统统计和CPU成本模型的关键点是,一般来说,系统统计和相关公式将自动确保公平的竞争环境。但是,与优化程序参数不同,它通常通过调整 FTS 的相关成本(而不是索引访问)来实现此目的,因为计算与多块 FTS 相关的真实成本和等待时间,但除以单块读取的单位并以单块读取的单位表示。

因此,系统统计信息和 CPU 成本计算模型通常不会降低索引访问路径的相关成本,而是通过根据需要自动增加 FTS 的相关成本来创建一个均衡的游戏。

有待进一步讨论...

 

参考至:​​http://richardfoote.wordpress.com/2009/09/16/the-cbo-cpu-costing-model-and-indexes-another-introduction/​

如有错误,欢迎指正