首页 > 解决方案 > SQL Developer 中的不同解释计划与命令解释计划

问题描述

当我得到以下查询的解释计划时,我看到,两个表都有全表扫描。

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

这是我使用 explain plan 命令得到的解释计划。通过 EXPLAIN PLAN FOR 命令 在此处输入图像描述

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

但是,如果我通过 SQL 开发人员获得相同查询的解释计划,我会看到一个明显不同的解释计划。特别是,它在底部写入完整的表访问,但在它之上,它通过索引 rowid 写入表访问。

这是我从 SQL Developer 那里得到的解释计划。通过 SQL Developer 解释计划按钮 在此处输入图像描述

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

我的问题是,谁能一步一步解释SQL开发人员的解释计划?为什么 SQL Developer 和解释计划命令会生成不同的解释计划?

提前致谢。

标签: oracle-sqldevelopersql-execution-plan

解决方案


在 SQL Developer 中获取查询计划的方法有多种。

解释计划 在此处输入图像描述

缓存计划 在此处输入图像描述

DBMS_XPLAN 在此处输入图像描述

您使用哪种方法?您已经裁剪了图片,因此我们无法判断这是来自 V$SQL_PLAN 的缓存计划还是解释计划。

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

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

——这是一个适应性计划

Oracle Database 12c 中的自适应计划允许对执行计划进行运行时更改。这通常是因为统计数据对优化器撒谎。数据库认为有 5 行,但当它从索引或表中读取它们时,却发现 50,000 行。所以数据库去了,为了解决这个问题,我们要做其他事情。

所以我的建议——

收集关于您的两个表的统计信息:

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 - 使用上面显示的第二个或第三个选项。


推荐阅读