注册
达梦数据库sql优化入门之《执行计划》如何查看
专栏/技术分享/ 文章详情 /

达梦数据库sql优化入门之《执行计划》如何查看

dm-9527 2026/10/23 90 0 0
摘要

一、背景

为什么需要查看执行计划?
因为只看SQL文本和总耗时,很难知道sql慢在哪里;执行计划则会详细描述数据库如何获得这些数据,包括扫描方式、索引选择、表连接方式以及排序、聚合等处理步骤。

1.1 查看执行计划主要有以下目的:

  1. 确认访问路径:是否使用合适的索引,是否扫描了过多数据,是否存在大量回表。
  2. 检查连接过程:连接顺序和连接方式是否适合当前数据量,中间结果是否明显膨胀。
  3. 检查过滤位置:条件是否尽早减少数据,是否读取大量记录后才过滤。
  4. 识别估算偏差:优化器预计处理的数据量与实际情况是否相符,是否需要检查统计信息或数据分布。
  5. 验证优化效果:SQL 改写、索引调整后,比较访问路径、实际耗时和资源消耗,形成证据。

执行计划用于解释性能现象,但不能独立解释所有慢 SQL。锁等待、并发负载、存储响应和客户端取数也可能影响耗时,需要结合监控分析。优化器的选择依赖统计信息等输入,因此“有索引”并不代表一定应当使用索引。参见官方《查询优化》。

1.2 先区分三类信息

信息类型 回答的问题 典型获取方式 主要局限
预估执行计划 当前环境下,优化器准备怎样执行? EXPLAIN、EXPLAIN FOR、图形界面的执行计划入口 无法证明实际耗时与实际行数
实际执行计划及运行统计 某一次执行采用了什么计划、消耗了哪些资源? AUTOTRACE TRACE/TRACEONLY、SQL Monitor、ET 需要执行和采集,存在额外开销
缓存中的计划 服务器当前保留了哪些计划? VSQL_PLAN、VCACHEPLN 等 缓存可能淘汰,也不等于某次执行的完整统计

“实际采用的计划”不表示计划中的每个字段都是实测值;其中的 COST 等字段仍可能是优化器估算。是否提供实际行数及具体统计项,应以版本和输出为准。

二、获取方案和操作步骤总览

2.1 常用方案

方案 获取步骤 是否执行目标 SQL 适用场景
EXPLAIN 在目标 SQL 前加 EXPLAIN → 提交 → 查看文本计划树 否 快速检查扫描、索引及连接方式
EXPLAIN FOR 在目标 SQL 前加 EXPLAIN FOR → 提交 → 保存结构化结果 否 比较计划字段、整理分析报告
SET AUTOTRACE 选择模式 → 提交目标 SQL → 查看计划和统计 → 关闭跟踪 取决于模式 命令行复现与整体资源分析
SQL Monitor 开启监控 → 执行 SQL → 取得执行号 → 调用报告函数 采集需要执行;读取报告无需重跑 分析某次执行的详细情况
ET 开启操作符监控 → 执行 SQL → 取得执行号 → CALL ET 采集需要执行;读取结果无需重跑 定位耗时操作符
图形化工具 连接数据库 → 选中 SQL → 点击执行计划;实际统计另走监控入口 取决于入口 日常开发、直观阅读
缓存计划与动态视图 定位 SQL → 查询缓存或节点视图 → 必要时导出 读取现有信息无需重跑 排查应用与手工测试计划不一致

2.2 通用准备

  1. 记录数据库版本、连接用户、当前模式、SQL 原文和绑定参数类型及值。
  2. 确认表和索引存在,并具备目标 SQL 所需权限;监控视图和参数操作可能需要额外授权。
  3. 先查看预估计划,再按需要采集实际执行信息。
  4. 实际执行类方案应确认目标 SQL 的影响,尤其是 INSERT、UPDATE、DELETE。
  5. 保存计划、执行号、采集时间和参数状态,结束后恢复本次修改的设置。

下文统一使用业务表示例 APP.EMPLOYEE,假定存在 EMPLOYEE_ID、EMPLOYEE_NAME、DEPARTMENT_ID 三个字段。运行时请替换为实际对象。

三、各方案详细说明

3.1 EXPLAIN:快速获取预估执行计划

执行命令:

EXPLAIN SELECT EMPLOYEE_ID, EMPLOYEE_NAME FROM APP.EMPLOYEE WHERE DEPARTMENT_ID = 10;

查看计划中的扫描节点、索引名称、过滤条件和连接方式。它适合回答“当前优化器是否选择了预期访问路径”。

优点:

  • 命令简单,不需要执行目标查询或 DML。
  • 适合先分析耗时较长、暂不适合实际运行的语句。
  • 可快速比较 SQL 改写前后的计划结构。

缺点:

  • 无法获得本次 SQL 的实际资源消耗。
  • 计划依赖当前统计信息、参数和编译环境。
  • 把应用绑定变量替换为字面量后,手工生成的计划可能与应用实际使用的计划不同。

**适用场景:**优化前的初步检查,以及改写或索引调整后的计划验证。

官方语法及权限要求参见《数据查询语句》4.19。

3.2 EXPLAIN FOR:以结构化结果查看计划

执行命令:

EXPLAIN FOR SELECT EMPLOYEE_ID, EMPLOYEE_NAME FROM APP.EMPLOYEE WHERE DEPARTMENT_ID = 10; -- 也可以为计划命名 EXPLAIN AS EMP_DEPT_PLAN FOR SELECT EMPLOYEE_ID, EMPLOYEE_NAME FROM APP.EMPLOYEE WHERE DEPARTMENT_ID = 10;

它将计划作为结果集返回,便于导出。重点字段包括 OPERATION、TAB_NAME、IDX_NAME、ROW_NUMS、COST、FILTER 和 JOIN_COND,还可包含分区范围及优化建议。

优点:

  • 字段明确,便于保存、筛选和比较。
  • 比文本计划提供更丰富的描述信息。

缺点:

  • 仍属于预估计划,不提供目标 SQL 的实际耗时。
  • 结果列较多,初学者需要结合字段说明阅读。
  • 优化建议需要结合业务和实际测试判断,不能直接据此创建索引。

**适用场景:**计划对比、分析记录和结构化导出。

语法和结果说明参见官方《数据查询语句》EXPLAIN FOR。

3.3 SET AUTOTRACE:查看访问路径或实际执行信息

这是 DIsql 客户端命令,应在 DIsql 中使用,不能默认作为普通 SQL 发送给任意 JDBC 工具。

模式区别:

模式 是否执行目标 SQL 输出特点
OFF 正常执行 关闭自动跟踪
NL 否 显示嵌套循环相关操作符
INDEX / ON 否 显示扫描方式、表名及索引
TRACE 是 查询结果、实际计划和部分执行统计
TRACEONLY 是 实际计划和部分执行统计,不打印查询结果集

执行命令:

-- 前提:ENABLE_MONITOR、ENABLE_MONITOR_DMSQL 已按当前版本要求开启。 -- 记录 MONITOR_SQL_EXEC 原值后,在本会话开启操作符监控。 SF_SET_SESSION_PARA_VALUE('MONITOR_SQL_EXEC', 1); SET AUTOTRACE TRACEONLY SELECT EMPLOYEE_ID, EMPLOYEE_NAME FROM APP.EMPLOYEE WHERE DEPARTMENT_ID = 10; SET AUTOTRACE OFF -- 分析完成后,将本次修改的监控参数恢复为原值。

**优点:**适合脚本复现,可同时观察实际计划、逻辑读、物理读及排序等统计。

**缺点:**TRACE 类模式需要真实执行,详细监控增加开销;TRACE 输出大量结果时还会增加客户端显示负担。

**注意:**达梦的 ON 不等同于其他数据库的同名模式;TRACEONLY 仍会执行 DML。它不打印查询结果,也不能据此认为执行过程完全没有网络开销。

模式和监控前提参见官方《DIsql 环境变量设置》3.3.19。

3.4 SQL Monitor:获取某次执行的监控报告

本文的 SQL Monitor 指达梦 DBMS_SQLTUNE.REPORT_SQL_MONITOR。不要直接套用其他数据库的监控命令、Hint 或报告选项。

执行步骤与命令:

-- 前提:ENABLE_MONITOR = 1,且当前版本支持该系统包。 SF_SET_SESSION_PARA_VALUE('MONITOR_SQL_EXEC', 1); SELECT EMPLOYEE_ID, EMPLOYEE_NAME FROM APP.EMPLOYEE WHERE DEPARTMENT_ID = 10; -- 记录上面语句返回的执行号;以下 12345 仅为示例。 -- 在 DIsql 中增大 CLOB 显示长度,避免报告被截断。 SET LONG 1000000 SELECT DBMS_SQLTUNE.REPORT_SQL_MONITOR( SQL_EXEC_ID => 12345 ) FROM DUAL;

**优点:**以报告形式集中呈现一次执行的信息,适合检查计划节点、耗时和资源消耗,也便于留档。

**缺点:**依赖版本、系统包和监控数据;未提前采集或数据已淘汰时,不能保证事后补回。报告较长,需要正确处理 CLOB 输出。

**适用场景:**复杂 SQL 的深入分析和一次执行的性能取证。MPP 环境需在执行 SQL 的当前节点查询报告。报告参数和返回类型参见官方《DBMS_SQLTUNE 包》。

3.5 ET:定位实际耗时操作符

执行步骤与命令:

-- 前提:ENABLE_MONITOR = 1。 SF_SET_SESSION_PARA_VALUE('MONITOR_SQL_EXEC', 1); SELECT EMPLOYEE_ID, EMPLOYEE_NAME FROM APP.EMPLOYEE WHERE DEPARTMENT_ID = 10; -- 使用目标语句的执行号替换示例值。 CALL ET(12345);

重点关注 OP(操作符)、TIME(微秒)、PERCENT(耗时占比)、RANK(耗时排名)、SEQ(计划节点号)和 N_ENTER(进入次数)。先找高耗时节点,再判断是否存在反复调用或数据处理过多。

**优点:**按执行号定位,能够把分析范围缩小到具体操作符;适合解释复杂计划的主要时间消耗。

**缺点:**需要提前启用监控;只有文本和执行号、没有保留的监控数据时,未必能查询成功。它用于节点开销分析,不能代替锁等待等系统诊断。

**适用场景:**已经确认 SQL 较慢,需要定位扫描、连接或排序等节点的实际开销。各版本开启条件可能不同,不应假设监控默认开启。参见官方《性能优化》4.2.3—4.2.4。

3.6 图形化工具:通过界面查看

操作步骤:

  1. 在 DM 管理工具 manager 中连接数据库并打开查询窗口。
  2. 输入或选中目标 SQL,点击“执行计划”入口;具体菜单和快捷键以所装版本为准。
  3. 阅读计划树中的对象、访问路径和过滤条件。
  4. 如需实际执行统计,按版本要求启用监控并执行 SQL,再通过执行号等入口查看分析结果。

DEM 的 SQL 开发模块也提供“执行计划”和“自动跟踪”等入口。其中“执行计划”相当于 EXPLAIN + SQL,不能因为采用图形显示就把它理解为实际执行统计。参见官方《DEM 使用手册》SQL 查询。

**优点:**计划树直观,适合交互分析和交流讲解。

**缺点:**不同工具和版本入口存在差异;截图不利于批量比较,建议同时保存 SQL 和文本计划。

**适用场景:**开发人员日常排查,以及需要直观展示计划结构的场景。

3.7 缓存计划和动态视图:观察服务器已有信息

手工 EXPLAIN 与应用表现不一致时,可以检查服务器缓存和已有监控记录。

执行命令:

-- 先确认当前版本字段。 DESC V$CACHEPLN DESC V$SQL_PLAN SELECT CACHE_ITEM, SQLSTR FROM V$CACHEPLN WHERE SQLSTR LIKE '%APP.EMPLOYEE%'; SELECT * FROM V$SQL_PLAN WHERE SQLSTR LIKE '%APP.EMPLOYEE%';

进一步定位一次执行时,可以查询 V$SQL_HISTORY 的 EXEC_ID,再读取已采集的节点信息或监控报告。SQL_ID、EXEC_ID、CACHE_ITEM 含义不同,不能互相替换。

**优点:**读取已有信息时无需重跑目标 SQL,适合观察应用环境;能够辅助排查缓存重用问题。

**缺点:**计划和监控数据可能淘汰;模糊匹配可能命中其他语句,需要核对全文、用户和执行上下文。缓存视图也不是永久历史仓库,不能仅凭存在一份缓存计划就断定某次执行使用了它。

V$CACHEPLN 依赖 USE_PLN_POOL != 0;执行节点监控另有 ENABLE_MONITOR、MONITOR_SQL_EXEC 等要求。视图定义和条件参见官方《系统管理员手册·附录 2》。

某些排障流程还会将缓存计划转储到服务器文件。此类操作涉及构建版本、事件语法、文件路径及权限,入门分析优先使用上述查询和报告入口,确需转储时按对应版本手册执行。

四、拿到计划后,先看什么

4.1 看操作符和数据访问路径

常见操作符 基本含义 初步检查方向
CSCN2 聚集索引全扫描,常表现为全表扫描 是否需要处理大量记录
CSEK2 聚集索引范围扫描 扫描范围是否合理
SSEK2 二级索引范围扫描 使用的索引及范围是否符合条件
SSCN2 二级索引全扫描 是否仍扫描了大量索引记录
BLKUP2 根据二级索引定位信息回表 回表次数和数据量是否过大
NEST LOOP、HASH JOIN 等 表连接操作 数据规模、连接条件及重复调用
SORT、聚合类操作符 排序或汇总处理 输入行数及实际资源消耗

操作符名称和后缀可能随版本变化。阅读时沿子节点到父节点理解数据流;多分支、并行和流水线执行不能仅靠文本上下顺序判断。具体解释参见官方《查询优化》。

4.2 用实际证据验证判断

  • 全表扫描不一定有问题:小表或需要读取大部分数据时,可能是合理选择。
  • 使用索引不一定更快:范围过大或回表过多时,仍可能消耗大量资源。
  • 不要只比较 COST:应同时记录实际耗时、逻辑读及处理数据量。
  • 比较前后应保持条件可比:使用相同参数、相近负载,并说明缓存状态。
  • 取数行为要与业务一致:只取第一页和读取全部结果可能呈现不同耗时。

五、推荐的入门排查流程

  1. 保存现场:记录原始 SQL、绑定值及类型、版本、用户和模式。
  2. 查看预估计划:用 EXPLAIN 检查访问路径;需要结构化比较时用 EXPLAIN FOR。
  3. 验证实际执行:允许复现时,用 AUTOTRACE TRACEONLY 查看实际计划和整体统计。
  4. 定位节点开销:用目标执行号查询 ET 或 SQL Monitor 报告。
  5. 核对应用差异:应用仍慢、手工执行正常时,检查会话环境、参数和缓存计划。
  6. 验证改动:围绕证据调整 SQL、索引或统计信息,再用可比条件复测并保存结果。
  7. 恢复采集设置:恢复本次修改的监控参数,保留必要报告。

建议每次至少保留:SQL 原文、绑定参数、环境版本、预估计划、实际执行号、实际统计、修改内容和对比结果。这样才能说明优化改变了什么,以及为什么有效。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服