有人能解释如何在Oracle解释计划中评估成本吗? 是否有任何特定的算法来确定查询的成本?
例如:全表扫描成本更高,索引扫描更低...... Oracle如何评估full table scan
,index range scan
等的案例?
此链接与我要求的相同:Question about Cost in Oracle Explain Plan
但是,任何人都可以通过一个例子来解释,我们可以通过执行explain plan
找到成本,但它在内部如何运作?
答案 0 :(得分:6)
有很多很多用于计算成本的特定算法。远不止这里可以实际讨论。乔纳森·刘易斯(Jonathan Lewis)在他的书Cost-Based Oracle Fundamentals中完成了基于成本的优化器如何决定查询成本方面所做的令人钦佩的工作。如果你真的很感兴趣,这将是最好的起点。
假设全表扫描的成本高于索引扫描,这是一种谬误。它取决于优化器对表中行数的估计以及优化器对查询将返回的行数的估计(反过来,这取决于优化器对各种谓词的选择性的估计),相对成本顺序读取与串行读取,处理器速度,磁盘速度,缓冲区缓存中块可用的概率,数据库的优化器设置,会话的优化器设置,PARALLEL
你的表和索引的属性,以及一大堆其他因素(这就是为什么它需要一本书真正开始深入研究这种事情)。通常,如果您的查询将返回表中的大部分行,并且如果查询将返回表中的一小部分行,则Oracle将更喜欢全表扫描。并且“小部分”通常比人们最初估计的要小得多 - 例如,如果您返回表中20-25%的行,例如,使用全表扫描几乎总是更好。
如果您尝试在查询计划中使用COST
列来确定计划是“好”还是“坏”,那么您可能会走错路。只有优化程序的估算值准确时,COST
才有效。但查询计划不正确的最常见原因是优化程序的估计不正确(统计信息不正确,Oracle对选择性的估计不正确等)。这意味着如果您看到一个成本为6的查询计划和一个成本为600万的该查询的不同版本的计划,那么成本为600万的计划完全有可能是更高效,因为低成本的计划错误地假设某些步骤将返回1行而不是100万行。
忽略COST
列并专注于CARDINALITY
列,您会更好。 CARDINALITY
是优化程序对计划每一步将返回的行数的估计。 CARDINALITY
是您可以直接测试和比较的东西。例如,如果您在计划中看到一个步骤涉及对没有谓词的表A的完全扫描,并且您知道A有大约100,000行,那么如果优化程序的CARDINALITY
估计值也是如此高或太低。如果它将基数估计为100或10,000,000,那么优化器几乎肯定要么错误地选择表扫描,要么将该数据提供给后续步骤,其中成本估计将非常不正确,导致它选择不良的连接顺序或一种糟糕的连接方法。它可能表明表A的统计数据不正确。另一方面,如果您发现每个步骤的基数估计值与现实相当接近,那么Oracle很有可能为查询选择了一个相当不错的计划。
答案 1 :(得分:1)
另一个开始理解CBO算法的地方是Wolfgang Breitling this paper。乔纳森刘易斯的书更详细,更新,但这篇论文是一个很好的介绍。
答案 2 :(得分:1)
在the 9i documentation中,甲骨文为成本制作了一个看起来很好的数学模型:
Cost = (#SRds * sreadtim + #MRds * mreadtim + #CPUCycles / cpuspeed ) / sreadtim
其中:
- #SDSs是单个块读取的数量
- #MRDs是多块读取的数量
- #CPUCycles是CPU周期数*)
- sreadtim是单块读取时间
- mreadtim是多块读取时间
- cpuspeed是每秒CPU周期数
因此,它可以很好地了解计算成本的因素。这就是为什么Oracle引入了收集系统统计信息的能力:为CPU速度等提供准确的值
现在我们快进the equivalent 11g documentation,我们发现数学已被粗略的解释所取代:
“优化程序查询方法估计的操作成本。 未确定表访问操作的成本。这个的价值 色谱柱没有任何特定的测量单位;它只是 用于比较执行计划成本的加权值。价值 此列的内容是CPU_COST和IO_COST列的函数。“
我认为这反映了这样一个事实:cost
不是一个非常可靠的执行时间指标。 Jonathan Lewis最近发布了一篇相关的博客文章。他展示了两个相似的查询;他们的解释计划不同,但他们有相同的费用。然而,当涉及到运行时,一个查询的执行速度比另一个慢得多。 Read it here