有人能解释一下Oracle解释计划中如何评估成本吗?是否有任何特定的算法来确定查询的成本?
例如:全表扫描成本较高,索引扫描成本较低。。。Oracle如何评估full table scan
、index range scan
等的案例。?
此链接与我所问的内容相同:Oracle解释计划中的成本问题
但有人能举例说明吗?我们可以通过执行explain plan
来找到成本,但它在内部是如何工作的?
计算成本有很多特定的算法。远远超出了这里可以实际讨论的范围。Jonathan Lewis在他的《基于成本的Oracle基础》一书中介绍了基于成本的优化器如何决定查询的成本,这一点令人钦佩。如果你真的感兴趣,那将是最好的开始。
假设全表扫描的成本将高于索引扫描,这是一种谬论。它取决于优化器对表中行数的估计和优化器对查询将返回的行数的评估(这反过来又取决于优化器对于各种谓词的选择性的估计)、顺序读取与串行读取的相对成本、处理器的速度、磁盘的速度、,缓冲区缓存中可用块的概率、数据库的优化器设置、会话的优化器设置,表和索引的PARALLEL
属性,以及一大堆其他因素(这就是为什么需要一本书才能真正开始深入研究这类事情)。通常,如果您的查询将返回表中很大一部分行,Oracle将更喜欢全表扫描,而如果查询将返回表格中很小一部分行,则更喜欢索引访问。"小部分"通常比人们最初估计的要小得多——例如,如果你返回了表中20-25%的行,那么使用全表扫描几乎总是更好的。
如果您试图在查询计划中使用COST
列来确定该计划是"好"还是"坏",那么您可能走错了路。只有当优化器的估计准确时,COST
才有效。但查询计划不正确的最常见原因是优化器的估计不正确(统计数据不正确,Oracle对选择性的估计不准确,等等)。这意味着,如果你看到一个查询计划的成本为6,而另一个查询版本的成本为600万,完全有可能具有600万成本的计划更有效,因为具有低成本的计划错误地假设某个步骤将返回1行而不是100万行。
忽略COST
列而专注于CARDINALITY
列会更好。CARDINALITY
是优化器对计划的每个步骤将返回的行数的估计。CARDINALITY
是可以直接测试和比较的东西。例如,如果您在计划中看到一个步骤涉及对没有谓词的表a进行全面扫描,并且您知道a大约有100000行,那么优化器的CARDINALITY
估计值是太高还是太低都会令人担忧。如果优化器估计基数为100或10000000,那么几乎可以肯定的是,优化器要么错误地选择了表扫描,要么将数据输入到稍后的步骤中,在该步骤中,其成本估计将严重不正确,导致它选择了糟糕的连接顺序或糟糕的连接方法。这可能表明表A中的统计数据是不正确的。另一方面,如果您看到每一步的基数估计都相当接近实际,那么Oracle很有可能为查询选择了一个相当好的计划。
另一个开始了解国会预算办公室算法的地方是Wolfgang Breitling的这篇论文。乔纳森·刘易斯的书更详细、更新,但这篇论文是一篇很好的引言。
在9i文档中,Oracle生成了一个具有权威性的成本数学模型:
Cost = (#SRds * sreadtim + #MRds * mreadtim + #CPUCycles / cpuspeed ) / sreadtim
其中:
- #SRD是单个块读取的数量
- #MRD是多块读取的次数
- #CPUCycles是CPU周期数*)
- sreadtim是单块读取时间
- mreadtim是多块读取时间
- cpuspeed是每秒的CPU周期
因此,它很好地了解了成本计算中的因素。这就是为什么Oracle引入了收集系统统计数据的能力:为CPU速度等提供准确的值
现在我们快进到等效的11g文档,我们发现数学已经被粗略的解释所取代:
"由优化器的查询方法估计的操作成本。未确定表访问操作的成本。这个的价值列并没有任何特定的计量单位;它只是用于比较执行计划成本的加权值。价值的函数是CPU_COST和IO_COST列的函数。"
我认为这反映了一个事实,即cost
不是一个非常可靠的执行时间指标。乔纳森·刘易斯最近发表了一篇相关的博客文章。他展示了两个看起来相似的问题;他们的解释计划不同,但成本相同。然而,在运行时,一个查询的执行速度要比另一个慢得多。请在此处阅读。