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]

解读执行计划要从内向外看:

  1. SSEK2表示使用IDX_EMP_DEPT索引查找dept_no=10的记录
  2. BLKUP2表示通过索引回表获取完整数据
  3. PRJT2选择要返回的列
  4. 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,特别是生产环境中突然变慢的查询。操作分为三步:

  1. 查询缓存计划信息:
SELECT sqlstr, cache_item FROM v$cachepln 
WHERE sqlstr LIKE '%关键表名%';
  1. 导出执行计划到trace文件:
ALTER SESSION SET EVENTS 'immediate trace name plndump level 140357593086048';
  1. 查看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优化:

  1. 先用EXPLAIN快速检查基本执行路径
  2. 使用AUTOTRACE ON验证索引使用情况
  3. 复杂SQL使用ET分析各阶段耗时

生产环境性能问题:

  1. 通过数据字典定位高消耗SQL
  2. 用PLNDUMP检查当前缓存中的执行计划
  3. 在测试环境用ET复现并分析问题

紧急故障排查:

  1. 直接使用AUTOTRACE TRACE获取实时信息
  2. 必要时启用ET详细监控
  3. 结合PLNDUMP检查计划是否异常

在实际项目中,我通常会组合使用这些工具。比如先用EXPLAIN快速检查,再用AUTOTRACE确认实际执行情况,遇到复杂性能问题时启用ET。记住,没有放之四海而皆准的方案,关键是根据具体场景选择最适合的工具组合。

更多推荐