【问题标题】:Why Oracle uses Range Scan and Fast Full Scan on same index?为什么 Oracle 在同一索引上使用范围扫描和快速全扫描?
【发布时间】:2020-12-04 04:17:18
【问题描述】:

我遇到了一个奇怪的情况:

有一个查询(对象的名称当然不同)

grante[pm, st] 上还有一个索引 GRANTEE_INDEX_01(每个表都有相似的索引 [pm,st]),我不知道为什么 - 但是 oracle 对同一索引进行索引范围扫描和快速全扫描,而且我无法将其从他的……核心中敲出。

实际上没有性能问题,至少没有人抱怨。我只想知道为什么会这样?

【问题讨论】:

  • 您有实际的性能问题吗?成本和基数如此之低,很难理解你为什么要问这个问题。执行查询需要多长时间?您预计经过的时间是多少?
  • Acutally 没有性能问题,至少没有人抱怨......但我遇到了它,它正在杀死我:)
  • 如果出现公共问题,最好使用标准 dbms_xplan.display_cursor() 显示计划,并将第三个参数设置为“ADVANCED”,因为并非所有人都知道您的工具,而 dbms_xplan 显示的信息比您多得多假如。看起来您正在使用 pl/sql 开发人员。您可以将其配置为至少显示过滤器和访问谓词

标签: sql oracle performance query-optimization oracle12c


【解决方案1】:

线索是[Oracle 12c]。您在这里看到的是自适应光标功能的体现。这是 Oracle 在 12c 中添加的(有争议的)功能,如果优化器认为使用现有计划运行得太慢,它允许优化器更改为不同的计划。

Oracle 实际上为您的查询提出了两个计划,一个使用散列连接,另一个使用嵌套循环。它正在执行一个计划,但正在使用 STATISTICS COLLECTOR 操作来监视另一个计划;这就是 CBO 决定是否切换到其他计划的方式。您在 GRANTEE_INDEX_01 上看到了两次命中,因为它在两个计划中都使用了。

顺便说一句,解释计划应该有一些额外的信息(尝试文本或 HTML 视图),它们会告诉你这一点。

Note
-----
   - this is an adaptive plan (rows marked '-' are inactive)

非活动行是备用计划连接和 STATISTICS COLLECTOR 操作。

如果您想了解更多信息,Maria Colgan 在on the official Oracle blog site 中写道。难免,Tim Hall 在他的Oracle-Base site 上也有一篇好文章。


我将自适应光标描述为有争议的。这是许多 DBA 在刚推出并关闭时不喜欢的功能。他们的反对主要集中在它的不可预测性上:DBA 喜欢他们的 SQL 有稳定的执行计划。 此外,我还将包括 Chris Saxon 的评论,因为他比我更接近产品:

我认为引起最多争议的是自适应统计数据,而不是自适应计划。这就是为什么它被分成two parameters in 12.2,默认情况下自适应计划和自适应统计关闭。

【讨论】:

  • 您始终可以选择将优化器降级为 11g 行为。
  • 我认为引起争议的是自适应统计,而不是自适应计划。这就是为什么它被分成two parameters in 12.2,默认情况下自适应计划和自适应统计关闭
  • @ChrisSaxon - 感谢您的澄清。到目前为止,我对它的体验仅限于关闭它的 12c R1 数据库:)
  • @ChrisSaxon 我同意你的观点,但如果我们需要检查 11g 与 12c 的行为,最好的选择是回到 11g 优化器设置。两个参数拆分在12.1和12.2之间更大的区别
  • @mohdatif - Seeker 评论 “实际上没有性能问题,至少没有人抱怨。” 他们只是想要解释计划的解释,没有必要关闭该功能。
【解决方案2】:

区别来自于索引的定义。如果您有复合索引,则索引定义中列的顺序很重要。在您的示例中,pm 列在 st 列之前定义。这将影响该索引的组织方式。由于这个因素,您会看到该索引的两种不同用法。

【讨论】:

  • 是的,这是一个复杂的索引,它还有另外 3 列,它们当然不会出现在此查询中...但我仍然不明白为什么 oracle 需要执行 2 个操作...
【解决方案3】:

" INDEX FAST FULL SCAN 等效于 FULL TABLE SCAN,但对于索引"

能否请您粘贴您的受赠者表结构并解释使用计划

select * from table(dbms_xplan.display)

这里使用索引范围扫描根据where子句过滤行,然后使用索引快速全扫描访问行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-08-10
    • 2015-01-25
    • 2021-09-04
    • 2015-01-27
    • 2020-09-09
    • 1970-01-01
    • 2015-10-19
    • 1970-01-01
    相关资源
    最近更新 更多