SQL Developer vs Explain Plan for command 中的不同解释计划

Different Explain Plans in SQL Developer vs Explain Plan for command

当我得到以下查询的解释计划时,我看到 table 都进行了完整的 table 扫描。

SELECT *
  FROM employees e,
       departments d
 WHERE e.employee_id = d.manager_id;

这是我用解释计划命令得到的解释计划。 by EXPLAIN PLAN FOR command

https://i.hizliresim.com/JZdB2o.jpg https://hizliresim.com/JZdB2o https://pasteboard.co/HO9ARcl.jpg

但是,如果我与 SQL 开发人员一起获得相同查询的解释计划,我会看到一个明显不同的解释计划。 特别是,它在底部写 table 访问完全,但在它上面,它写 table 按索引 rowid 访问。

这是我从 SQL 开发人员那里得到的解释计划。 by SQL Developer Explain Plan button

https://i.hizliresim.com/DYoYbv.jpg https://hizliresim.com/DYoYbv https://pasteboard.co/HO9BxfA.jpg

我的问题是,任何人都可以逐步解释 SQL 开发人员 的 解释计划吗?为什么 SQL 开发人员和解释计划命令生成不同的解释计划?

提前致谢。

在 SQL Developer 中有几种不同的方法可以获取查询计划。

解释计划

缓存计划

DBMS_XPLAN

您使用的是哪种方法?您对图片进行了裁剪,以至于我们无法判断这是来自 V$SQL_PLAN 的缓存计划还是解释计划。

现在,进入问题的关键 - 不要使用解释计划。它可能不可靠。它向您展示了一个可能 运行 的计划 - 它没有向您展示已经或将要使用的实际计划。

还要在您的计划输出中注意这一点 -

-- this is an adaptive plan

Oracle Database 12c 中的自适应计划允许 运行 对执行计划进行时间更改。它通常发生是因为统计数据对优化器说谎。数据库认为有 5 行,但是当它从索引或 table 中读取它们时,它发现了 50,000 行。所以数据库走了,管它呢,我们要做点别的事情。

所以我的建议 -

收集关于你的两个 table 的统计数据:

BEGIN
    dbms_stats.gather_table_stats(ownname => 'HR', tabname => 'EMPLOYEES', estimate_percent => 100);
    dbms_stats.gather_table_stats(ownname => 'HR', tabname => 'DEPARTMENTS', estimate_percent => 100);
END;

那么,运行又是你的计划。除了这一次,不要使用 EXPLAIN PLAN FOR - 使用上面显示的第二个或第三个选项。

您看到的是自适应计划的产物;您实际上在输出中看到了计划的两个版本。灰色线条是未执行的计划版本。