达梦数据库实战:五种SQL执行计划分析方法对比与应用场景
1. 执行计划分析的重要性与达梦数据库工具概览
SQL执行计划就像是数据库系统的"导航路线",它决定了查询数据的最佳路径。想象一下你要从北京到上海,可以选择高铁、飞机或者自驾,每种方式的时间和成本都不同。数据库执行计划就是优化器为SQL语句设计的"出行方案",直接影响查询性能。
在达梦数据库中,我们主要使用五种工具来分析执行计划:
- EXPLAIN:快速查看预估执行计划,不实际执行SQL
- AUTOTRACE:在DISQL中获取执行计划和统计信息
- PLNDUMP:从缓存中提取已执行SQL的计划
- ET:监控SQL执行时的详细耗时统计
- 数据字典视图:查询历史SQL的执行信息
这些工具各有特点,就像医生诊断病情时会用到听诊器、X光、CT等不同设备一样。下面我会详细介绍每种工具的使用场景和实战技巧。
2. EXPLAIN:快速预估执行计划分析
2.1 基础用法与实战示例
EXPLAIN是日常开发中最常用的工具,它的特点是不实际执行SQL,只展示优化器预估的执行路径。基本语法非常简单:
EXPLAIN SELECT * FROM employees WHERE dept_no = 10;
执行结果类似这样:
1 #NSET2: [3, 2450, 315]
2 #PRJT2: [3, 2450, 315]; exp_num(11), is_atom(FALSE)
3 #BLKUP2: [3, 2450, 315]; IDX_EMP_DEPT(EMPLOYEES)
4 #SSEK2: [3, 2450, 315]; scan_type(ASC), IDX_EMP_DEPT(EMPLOYEES), scan_range[10,10]
解读执行计划要从内向外看:
- SSEK2表示使用IDX_EMP_DEPT索引查找dept_no=10的记录
- BLKUP2表示通过索引回表获取完整数据
- PRJT2选择要返回的列
- NSET2将结果返回给客户端
2.2 EXPLAIN FOR高级功能
EXPLAIN FOR提供了更丰富的信息,包括:
- 分区表的分区裁剪信息
- 索引使用建议
- 执行计划保存到临时表方便对比
EXPLAIN AS plan1 FOR
SELECT e.name, d.dname
FROM employees e JOIN departments d ON e.dept_no = d.dept_no;
执行后可以查询临时表对比不同计划:
SELECT * FROM SYS."##PLAN_TABLE"
WHERE plan_name IN ('plan1','plan2')
ORDER BY plan_id, level_id;
我在项目中曾用这个功能发现一个关键查询突然改变了执行计划,原来是统计信息过期导致索引未被使用,及时更新统计信息后性能提升10倍。
3. AUTOTRACE:实时执行统计与计划分析
3.1 AUTOTRACE模式详解
AUTOTRACE在DISQL中使用,有多种模式:
| 模式 | 是否执行SQL | 输出内容 | 适用场景 |
|---|---|---|---|
| OFF | 是 | 只显示结果 | 生产环境常规查询 |
| NL | 否 | 嵌套循环部分 | 检查连接方式 |
| INDEX | 否 | 索引使用情况 | 验证索引选择 |
| ON | 否 | 完整执行计划 | 开发调试 |
| TRACE | 是 | 计划+统计信息 | 性能诊断 |
| TRACEONLY | 是 | 计划+统计信息(无结果) | 大数据量查询 |
3.2 实战案例:定位全表扫描问题
假设我们发现一个页面加载很慢,在DISQL中开启TRACE模式分析:
SET AUTOTRACE TRACE
SELECT * FROM orders WHERE customer_id = 100 AND status = 'SHIPPED';
输出显示:
1 #NSET2: [1500, 50000, 328]
2 #PRJT2: [1500, 50000, 328]; exp_num(8)
3 #SLCT2: [1500, 50000, 328]; (ORDERS.CUSTOMER_ID = 100 AND ORDERS.STATUS = 'SHIPPED')
4 #CSCN2: [1500, 1000000, 328]; ORDERS
这里CSCN2表示全表扫描,虽然customer_id有索引但未被使用。通过创建复合索引解决问题:
CREATE INDEX idx_orders_customer_status ON orders(customer_id, status);
4. PLNDUMP:缓存执行计划深度解析
4.1 使用场景与操作步骤
PLNDUMP适合分析已经执行过的SQL,特别是生产环境中突然变慢的查询。操作分为三步:
- 查询缓存计划信息:
SELECT sqlstr, cache_item FROM v$cachepln
WHERE sqlstr LIKE '%关键表名%';
- 导出执行计划到trace文件:
ALTER SESSION SET EVENTS 'immediate trace name plndump level 140357593086048';
- 查看trace文件(默认在$SYSTEM_PATH/trace目录)
4.2 常见问题处理
- 找不到缓存计划:可能已被淘汰,调整USE_PLN_POOL参数增大缓存
- trace文件生成失败:尝试不指定路径,使用默认目录
- 计划显示不全:确认SQL已完整执行
我曾用这个方法发现一个夜间批处理变慢的问题,原来是缓存中的执行计划被错误地重用,清理特定缓存后恢复正常:
CALL SP_CLEAR_PLAN_CACHE(140357593086048);
5. ET工具:执行耗时精准分析
5.1 ET配置与使用指南
ET是性能调优的利器,可以精确统计每个操作符的耗时。使用前需要开启监控参数:
-- 系统级参数(通常已开启)
SP_SET_PARA_VALUE(1,'ENABLE_MONITOR',1);
SP_SET_PARA_VALUE(1,'MONITOR_TIME',1);
-- 会话级参数
SF_SET_SESSION_PARA_VALUE('MONITOR_SQL_EXEC',1);
执行SQL后会显示执行号,然后调用ET分析:
SELECT /*+ INDEX(emp idx_emp_dept) */ * FROM emp WHERE dept_no = 10;
ET(12345);
输出示例:
OP TIME(us) PERCENT RANK
---------------------------------
NSET2 1500 15% 3
PRJT2 2000 20% 2
HASH JOIN 6500 65% 1
5.2 实战案例:定位连接性能瓶颈
某次调优中,ET显示HASH JOIN耗时占比85%,检查发现是小表驱动大表导致。改为NESTED LOOP并添加适当索引后,性能提升70%:
SELECT /*+ USE_NL(orders, items) */ *
FROM orders JOIN items ON orders.id = items.order_id
WHERE orders.create_date > '2023-01-01';
6. 数据字典视图:历史执行信息查询
6.1 核心视图与字段解析
当ENABLE_MONITOR=1时,可以通过以下视图查询历史执行信息:
- V$SQL_HISTORY:SQL基础信息与资源消耗
- V$SQL_NODE_HISTORY:执行计划节点详情
- V$SQL_NODE_NAME:操作符类型说明
典型查询:
SELECT
a.exec_id, c.sql_text, b.name,
a.time_used/1000 as "ms", a.n_enter
FROM
v$sql_node_history a
JOIN
v$sql_node_name b ON a.type$ = b.type$
JOIN
v$sql_history c ON a.exec_id = c.exec_id
WHERE
c.sql_text LIKE '%关键表%'
ORDER BY
a.time_used DESC;
6.2 生产环境应用案例
在一次系统升级后,通过分析历史视图发现某个查询的平均执行时间从50ms增长到500ms。对比升级前后的执行计划,发现优化器参数变化导致索引选择不同,通过Hint固定执行计划后恢复性能。
7. 工具对比与选型指南
7.1 五种方法特性对比
| 工具 | 是否执行SQL | 获取时机 | 输出内容 | 开销 | 适用场景 |
|---|---|---|---|---|---|
| EXPLAIN | 否 | 事前 | 预估计划 | 低 | 开发测试 |
| AUTOTRACE | 可选 | 实时 | 计划+统计 | 中 | 交互式调优 |
| PLNDUMP | 已执行 | 事后 | 缓存计划 | 低 | 生产问题诊断 |
| ET | 是 | 实时 | 详细耗时 | 高 | 性能瓶颈定位 |
| 数据字典 | 已执行 | 事后 | 历史执行信息 | 低 | 长期监控分析 |
7.2 典型场景推荐方案
开发阶段SQL优化:
- 先用EXPLAIN快速检查基本执行路径
- 使用AUTOTRACE ON验证索引使用情况
- 复杂SQL使用ET分析各阶段耗时
生产环境性能问题:
- 通过数据字典定位高消耗SQL
- 用PLNDUMP检查当前缓存中的执行计划
- 在测试环境用ET复现并分析问题
紧急故障排查:
- 直接使用AUTOTRACE TRACE获取实时信息
- 必要时启用ET详细监控
- 结合PLNDUMP检查计划是否异常
在实际项目中,我通常会组合使用这些工具。比如先用EXPLAIN快速检查,再用AUTOTRACE确认实际执行情况,遇到复杂性能问题时启用ET。记住,没有放之四海而皆准的方案,关键是根据具体场景选择最适合的工具组合。
更多推荐

所有评论(0)