SQL 执行计划核心手册:读懂执行计划,搞定慢查询

SQL 执行计划(SQL Execution Plan)是数据库查询优化器(Query Optimizer)为 SQL 语句生成的具体执行方案,它展示了数据库将如何(或已经如何)执行一条 SQL 查询。通过分析执行计划,开发者可以了解查询的性能瓶颈,从而进行优化。

一、执行计划的作用

  1. 性能诊断:识别慢查询的原因(如全表扫描、索引失效、连接方式不佳等)。
  2. 优化指导:指导开发者调整 SQL 写法(如添加索引、修改连接条件、重写子查询等)。
  3. 理解执行逻辑:明确数据库执行 SQL 时的步骤(如连接顺序、数据过滤顺序、聚合方式等)。

二、获取执行计划的方法

不同数据库获取执行计划的方式略有差异,以下是主流数据库的方法:

1. MySQL

  • 查看预估执行计划(未实际执行 SQL):
    EXPLAIN SELECT * FROM users WHERE age > 20;
    
  • 查看实际执行计划(需开启 profiling):
    SET profiling = 1; -- 开启 profiling
    SELECT * FROM users WHERE age > 20; -- 执行 SQL
    SHOW PROFILE FOR QUERY 1; -- 查看执行详情(1 是查询 ID)
    

2. Oracle

  • 查看预估执行计划
    EXPLAIN PLAN FOR SELECT * FROM users WHERE age > 20;
    SELECT * FROM TABLE(DBMS_XPLAN.DISPLAY); -- 展示执行计划
    
  • 查看实际执行计划(需开启追踪):
    ALTER SESSION SET SQL_TRACE = TRUE; -- 开启追踪
    SELECT * FROM users WHERE age > 20;
    ALTER SESSION SET SQL_TRACE = FALSE; -- 关闭追踪
    -- 然后查看追踪文件(需通过 TKPROF 工具分析)
    

3. PostgreSQL

  • 查看预估执行计划
    EXPLAIN SELECT * FROM users WHERE age > 20;
    
  • 查看实际执行计划(执行 SQL 并展示计划):
    EXPLAIN ANALYZE SELECT * FROM users WHERE age > 20;
    

4. SQL Server

  • 查看预估执行计划(SSMS 图形化界面或 T-SQL):
    SET SHOWPLAN_TEXT ON; -- 文本格式
    SELECT * FROM users WHERE age > 20;
    SET SHOWPLAN_TEXT OFF;
    
  • 查看实际执行计划
    SET STATISTICS PROFILE ON; -- 文本格式
    SELECT * FROM users WHERE age > 20;
    SET STATISTICS PROFILE OFF;
    

三、执行计划核心组件解析

以 MySQL 的 EXPLAIN 输出为例,核心字段含义如下(其他数据库类似):

字段含义
id查询的执行顺序(相同 ID 表示同一层级,ID 越大优先级越高,子查询 ID 通常更大)。
select_type查询类型(如 SIMPLE 简单查询、SUBQUERY 子查询、DERIVED 派生表、JOIN 连接查询)。
table当前执行步骤操作的表(可能是表名、别名,或派生表的标识如 <derived2>)。
type访问类型(核心性能指标),优先级从高到低:system > const > eq_ref > ref > range > index > ALL
possible_keys可能使用的索引(优化器认为潜在可用的索引)。
key实际使用的索引(NULL 表示未使用索引)。
key_len使用的索引长度(越长表示索引利用率越高,如联合索引使用的字段数越多)。
ref索引匹配的条件(如 const 表示常量匹配,users.age 表示关联其他表的字段)。
rows预估扫描的行数(值越小越好,说明过滤效果好)。
Extra额外信息(关键性能提示),如 Using index(覆盖索引)、Using filesort(文件排序,需优化)、Using temporary(临时表,需优化)等。

关键字段详解

1. type(访问类型)
  • system:表中只有一行数据(如 SELECT * FROM dual),性能最好。
  • const:通过主键或唯一索引查询,匹配一行数据(如 SELECT * FROM users WHERE id = 1)。
  • eq_ref:多表连接时,被连接表通过主键 / 唯一索引匹配,每行只匹配一次(如 JOIN orders ON users.id = orders.user_idorders.user_id 是主键)。
  • ref:通过非唯一索引匹配(如 SELECT * FROM users WHERE name = '张三'name 是普通索引)。
  • range:索引范围扫描(如 WHERE age BETWEEN 20 AND 30WHERE id > 100)。
  • index:全索引扫描(扫描整个索引树,比 ALL 快,因为索引数据量通常比表数据小)。
  • ALL:全表扫描(性能最差,需避免,通常是未建索引或索引失效导致)。
2. Extra(额外信息)
  • Using index:使用覆盖索引(查询的字段全部在索引中,无需回表查询数据行),性能优秀。
  • Using filesort:无法利用索引排序,需在内存或磁盘中进行文件排序(耗时高,需优化,如给排序字段建索引)。
  • Using temporary:使用临时表存储中间结果(如 GROUP BY 或 UNION 未命中索引时),性能差,需优化。
  • Using join buffer:多表连接时,使用连接缓冲区存储中间结果(通常是连接字段未建索引,需优化)。
  • Impossible WHEREWHERE 条件恒为假(如 WHERE 1 = 0),无需扫描数据。

四、执行计划分析示例

示例 1:全表扫描(需优化)

EXPLAIN SELECT * FROM users WHERE age > 20;

输出关键信息:

  • type: ALL(全表扫描)
  • key: NULL(未使用索引)
  • rows: 10000(预估扫描 1 万行)

优化方案:给 age 字段建索引:

CREATE INDEX idx_users_age ON users(age);

示例 2:索引失效(需优化)

-- 索引 idx_users_name 存在,但查询条件使用函数
EXPLAIN SELECT * FROM users WHERE UPPER(name) = 'ZHANGSAN';

输出关键信息:

  • type: ALL(全表扫描)
  • key: NULL(索引失效)

优化方案:避免在索引字段上使用函数,或改⽤函数索引(MySQL 8.0+):

-- 方案 1:修改 SQL(不推荐,需业务允许)
SELECT * FROM users WHERE name = 'zhangsan';

-- 方案 2:创建函数索引(推荐)
CREATE INDEX idx_users_upper_name ON users((UPPER(name)));

示例 3:覆盖索引(性能优秀)

-- 索引 idx_users_age_name 包含 age 和 name 字段
EXPLAIN SELECT name FROM users WHERE age > 20;

输出关键信息:

  • type: range(索引范围扫描)
  • key: idx_users_age_name(使用索引)
  • Extra: Using index(覆盖索引,无需回表)

结论:无需优化,性能已达最优。

五、执行计划优化常见场景

  1. 全表扫描(type: ALL:给查询条件的字段建索引。
  2. 索引失效
    • 避免在索引字段上使用函数、运算(如 WHERE age + 1 = 21 改为 WHERE age = 20)。
    • 避免使用 !=<>IS NOT NULL(可能导致索引失效,可改⽤ BETWEEN 或 IN)。
    • 字符串查询需匹配字段类型(如 WHERE id = '1' 改为 WHERE id = 1,避免隐式类型转换)。
  3. 文件排序(Using filesort:给排序字段建索引(若有 WHERE 条件,可建联合索引,如 WHERE age > 20 ORDER BY name 建索引 idx_age_name)。
  4. 临时表(Using temporary
    • GROUP BY 字段建索引。
    • UNION 改 UNION ALL(若允许重复结果,避免去重操作)。
  5. 多表连接优化
    • 小表驱动大表(如 SELECT * FROM small_table t1 JOIN big_table t2 ON t1.id = t2.t1_id)。
    • 连接字段建索引(避免 Using join buffer)。

六、总结

SQL 执行计划是优化查询性能的核心工具,通过分析 typekeyExtra 等关键字段,可以快速定位性能瓶颈。优化的核心思路是:尽量让数据库使用高效的索引访问方式(如 refrange),避免全表扫描、文件排序、临时表等低效操作

在实际开发中,应养成 “先看执行计划,再优化 SQL” 的习惯,尤其是在处理大数据量查询时,执行计划的分析能显著提升系统性能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

canjun_wen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值