注册
达梦数据库 SQL 优化入门 —— 执行计划详解
专栏/技术分享/ 文章详情 /

达梦数据库 SQL 优化入门 —— 执行计划详解

LyC_Dd 2025/09/26 456 0 0
摘要

达梦数据库 SQL 优化入门 —— 执行计划详解

概述

SQL 性能问题的核心通常集中在 执行计划(Execution Plan)。执行计划是优化器为某条 SQL 生成的“执行路线图”,决定了数据访问方式、连接顺序、聚合与排序策略等。理解并能读懂执行计划,是每个开发者与 DBA 进行 SQL 优化的基础技能。

学习目标:能用通过查看执行计划快速判断 SQL 是否走索引,能用 ET 获取真实执行统计,从而定位性能瓶颈。


什么是执行计划

执行计划是数据库优化器基于 SQL 语句、表结构、索引与统计信息,进行成本估算后选择的一组执行步骤。它将 SQL 的执行过程拆成多个节点(操作符),每个节点表示一次表扫描、索引扫描、连接、聚合、排序或投影等操作。

执行计划和实际执行统计:

  • 估算计划(EXPLAIN)—— 不实际执行 SQL,返回优化器估算的执行步骤与代价。适合快速检查索引/连接方式。
  • 实际执行统计(ET / AUTOTRACE / Trace)—— 在真正执行 SQL 时收集的真实耗时与返回行数,能揭示估算与真实差距。

怎么查看执行计划

为了演示,我们新建一个员工信息表。

SET SCHEMA TEST; DROP TABLE IF EXISTS employees; -- 员工信息表(employees) CREATE TABLE employees ( id BIGINT PRIMARY KEY, -- 主键,演示时可手工赋值或用自增/sequence emp_no VARCHAR(20) NOT NULL, -- 员工工号(业务唯一键) name VARCHAR(100) NOT NULL, -- 员工姓名 dept_no INT, -- 部门编号 manager_id BIGINT, -- 直属领导(引用 employees.id,可为 NULL) hire_date DATE, -- 入职日期 salary DECIMAL(12,2), -- 薪资 email VARCHAR(200), -- 邮箱(建议唯一) phone VARCHAR(50), -- 电话 status VARCHAR(20) DEFAULT 'ACTIVE' -- 状态(ACTIVE/INACTIVE 等) ); -- 按部门查询常用索引 CREATE INDEX idx_emp_dept ON employees(dept_no); -- manager_id 用于自连接/查领导 CREATE INDEX idx_emp_manager ON employees(manager_id); -- email 设唯一索引(如果业务允许) CREATE UNIQUE INDEX ux_emp_email ON employees(email); -- 组合索引示例(覆盖某些按部门和薪资筛选并排序的查询) CREATE INDEX idx_dept_salary ON employees(dept_no, salary);

使用sqlark插入百万级数据

20250922162640imagepng

20250922163013imagepng

EXPLAIN(预估执行计划)

在命令行或客户端中使用 EXPLAIN

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], is_global(0)

该命令不会运行查询,只返回优化器选定的计划树(节点、估算行数、代价等)。适合开发时快速检查。对于执行计划的顺序,我们需要从里往外阅读:

  • SSEK2:在部门索引 IDX_EMP_DEPT 上查到 dept_no = 10,优化器估计会匹配 2450 条

  • BLKUP2:用这些索引记录去表里取完整行(也就是回表),预计需要做 2450 次表访问

  • PRJT2:从取回的行里挑出要返回的列或进行必要的计算。

  • NSET2:把结果收集并返回给客户端(共 2450 行)。

图形化管理工具

达梦自带的图形化管理工具支持一件查看执行计划,以树状图或表格形式展示计划节点、索引与估算信息。图形化界面更直观,适合入门学习。

20250922163250imagepng

表格显示

20250922163310imagepng

图形显示

20250922163333imagepng

文本显示

20250922163405imagepng

AUTOTRACE

disql下执行set autotrace trace开启AUTOTRACE功能,执行SQL语句,并打印实际的执行计划。

sf_set_session_para_value('MONITOR_SQL_EXEC',1); --开启sql监控参数 set autotrace trace; SELECT * FROM EMPLOYEES WHERE DEPT_NO = 10;

20250923010129imagepng

v$cachepln中保存了SQL缓冲区中的执行计划信息,这些则是我们真实的执行计划。在ini参数USE_PLN_POOL !=0时才统计。

USE_PLN_POOL = 1 #Query Plan Reuse Mode, 0: Forbidden; 1:strictly reuse, 2:parsing reuse, 3:mixed parsing reuse

根据v$cachepln中的cache_item可以获取实际执行计划信息

--先确认sql对应的执行计划缓存号cache_item select cache_item, sqlstr from v$cachepln where SQLSTR like '%SELECT * FROM EMPLOYEES WHERE DEPT_NO = 10;%';

20250923005834imagepng

-- 执行以下命令,打印出缓存计划到默认路径,默认路径在数据库实例目录的trace文件夹中 Alter session set events 'immediate trace name plndump,level 140334006185072';
#切换至trace文件夹,将缓存计划文件cat出来 cd /home/dmdba/dmdbms/data/DAMENG/trace cat [文件名]

执行计划的各个字段

EXPLAIN 或 GUI 输出通常包含以下关键字段:

  • 名称(操作符):表示节点类型,例如 TABLE SCANINDEX SCANNESTED LOOPHASH JOIN 等。
  • 附加信息:该操作具体使用的索引名、扫描范围或谓词等信息,判断为何选择此索引或会发生回表。
  • 代价(Cost):优化器估算的资源消耗指标,常用于不同计划间的比较,但不是绝对真实耗时。
  • 结果集(Rows):估算返回的行数(非常重要,估算偏差会导致错误计划)。
  • 行数据处理长度(Bytes/Row length):用于估算 IO 与内存消耗。
  • 描述:对操作符的简短可读说明,帮助快速理解该节点在做什么。

常见计划操作符速查

以下为常见操作符与简要含义:

  • CSCN2:聚集索引扫描或按聚集顺序扫描(类似全表扫描/聚集索引顺序扫描)。
  • SSEK2:二级索引扫描(先扫描索引,再回表定位数据)。
  • BLKUP2:回表 / 通过索引值访问表记录(会产生随机 IO)。
  • PRJT2:投影操作(计算或返回 select 列)。
  • NSET2:结果集收集(如合并、去重、临时结果缓存)。
  • HASH JOIN:哈希连接,适合大表的等值连接。
  • NESTED LOOP:嵌套循环连接,适合小表驱动或有高选择性索引的场景。

参考阅读:附录 4 执行计划操作符| 达梦技术文档


读执行计划的大致思路

逐步拆解一个较复杂的执行计划:

  1. 从顶层看业务意图:顶节点通常是 SELECT 的投影/聚合,判断是否有不必要的列或聚合。
  2. 自底向上定位数据来源:找到底层的表扫描/索引扫描,确认是否使用期望的索引或发生全表扫描。
  3. 检查连接方式与顺序:确定是 NESTED LOOP 还是 HASH JOIN,并判断连接驱动表是否合理。
  4. 关注估算行数 vs 实际行数:如果可用 ET / AUTOTRACE,比较估算与实际的偏差。
  5. 找出代价热点:按代价或真实耗时定位最“贵”的节点并优先优化。
  6. 检查回表 / 排序 / 临时使用:回表说明索引覆盖不完全,排序/分组可能造成磁盘临时空间使用。考虑是否可以通过覆盖索引或改写 SQL 减少这些开销?

ET(Execution Trace / SQL 监控)

什么是 ET

ET 是在 SQL 真正执行时记录实际耗时、各节点实际返回行数与各操作耗时的跟踪工具。它能直接揭示优化器估算与真实执行的差距,是定位瓶颈的利器。

怎么开启

达梦ET有一定的开销,默认不启用,我们可以通过设置启动以下三个参数来启用ET:

  • ENABLE_MONITOR

  • MONITOR_TIME

  • MONITOR_SQL_EXEC

其中,ENABLE_MONITOR和MONITOR_TIME默认已开启,如果未开启可以使用如下方法开启

SP_SET_PARA_VALUE(1,'ENABLE_MONITOR',1); SP_SET_PARA_VALUE(1,'MONITOR_TIME',1);

MONITOR_SQL_EXEC是会话级动态参数,可以设置只针对当前会话开启

SF_SET_SESSION_PARA_VALUE('MONITOR_SQL_EXEC',1);

执行SQL语句,我们会看到一个执行号,直接点这个执行号,即可调用ET

20250922172939imagepng

在知道执行号的情况下,也可以这样使用ET

CALL ET(843);

20250922173101imagepng

注意

在生产环境全面开启详细跟踪会带来较大开销,建议只对有问题的 SQL 或少数会话启用。

ET结果的各个字段

  • OP: 操作符

  • TIME(us): 时间开销,单位为微秒

  • PERCENT: 执行时间占总时间百分比

  • RANK: 执行时间耗时排序

  • SEQ: 执行计划节点号

  • N_ENTER: 进入次数


小结

通过上述的方法,我们可以查看一条sql语句的执行过程,并根据相关指标初步推断出性能瓶颈,进而启发sql优化的相关思路。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服