当前位置: 首页 > news >正文

MySQL EXPLAIN 使用详解与执行计划分析优化

MySQL EXPLAIN 使用详解与执行计划分析优化

一、什么是 EXPLAIN?

EXPLAIN 是 MySQL 提供的 SQL 语句分析工具,可以显示 SQL 语句在执行时的执行计划,包括表的访问顺序、使用的索引、连接类型、扫描行数等。通过分析 EXPLAIN 的输出结果,可以帮助我们发现 SQL 性能瓶颈,进行有针对性的优化。


二、EXPLAIN 的基本用法

EXPLAIN SELECT * FROM users WHERE email = 'test@example.com';

或者

EXPLAIN FORMAT=JSON SELECT * FROM users WHERE email = 'test@example.com';

三、EXPLAIN 输出字段详解

字段含义
id查询中每个 SELECT 子句的标识符,越大优先级越高
select_type查询类型(SIMPLE、PRIMARY、SUBQUERY、UNION等)
table当前访问的表名或别名
partitions匹配的分区(如有分区表)
type连接类型,反映表的访问方式(性能由好到差:system > const > eq_ref > ref > range > index > ALL)
possible_keys可能用到的索引
key实际使用的索引
key_len使用索引的长度
ref哪个字段或常量与 key 一起使用
rows预估需要读取的行数
filtered经过条件过滤后剩余的百分比(MySQL 5.7+)
Extra额外信息,如 Using index、Using where、Using filesort、Using temporary 等

四、type 连接类型说明(性能由好到差)

  • system/const:表只有一行数据或主键等值查询,效率最高
  • eq_ref:唯一索引等值查询
  • ref:非唯一索引等值查询
  • range:范围查询(如 between、>、<、in)
  • index:全索引扫描
  • ALL:全表扫描,性能最差

优化目标:
尽量让 type 为 consteq_refrefrange,避免 ALL


五、EXPLAIN 结果分析案例

1. 全表扫描(ALL)

EXPLAIN SELECT * FROM users WHERE age = 25;

如果 age 没有索引,type 显示为 ALL,rows 很大,说明是全表扫描。

2. 使用索引(ref/range)

CREATE INDEX idx_age ON users(age);
EXPLAIN SELECT * FROM users WHERE age = 25;

此时 type 变为 refrange,rows 显著减少,说明走了索引。

3. 覆盖索引(Using index)

EXPLAIN SELECT age FROM users WHERE age = 25;

Extra 字段出现 Using index,说明只用索引就能返回结果,无需回表,效率更高。

4. 联合索引与最左前缀

CREATE INDEX idx_name_age ON users(name, age);
EXPLAIN SELECT * FROM users WHERE name = 'Tom' AND age = 20;

只有 WHERE 条件从最左列开始连续使用,才能用到联合索引。


六、索引优化详解

1. 合理选择索引字段

  • 经常作为查询条件(WHERE)、排序(ORDER BY)、分组(GROUP BY)、连接(JOIN)的字段应加索引。
  • 选择区分度高的字段作为索引,区分度低(如性别、布尔值)不建议单独加索引。

2. 联合索引与最左前缀原则

  • 联合索引(如 idx_a_b_c(a, b, c))只有从最左列开始连续使用,索引才会生效。
  • 例如:WHERE a=1 AND b=2,可以用到 (a, b, c) 索引;WHERE b=2 无法用到。

3. 覆盖索引(索引覆盖查询)

  • 查询的字段全部在索引中,无需回表,效率极高。
  • 例如:SELECT id, name FROM users WHERE name='Tom'; 如果有联合索引 (name, id),则为覆盖索引。

4. 避免在索引列上使用函数或运算

  • WHERE DATE(create_time) = '2024-07-01',会导致索引失效。
  • 优化为:WHERE create_time >= '2024-07-01 00:00:00' AND create_time < '2024-07-02 00:00:00'

5. 合理利用唯一索引和主键

  • 唯一索引和主键查询效率最高,能直接定位唯一一行。

6. 控制索引数量

  • 索引不是越多越好,过多索引会影响写入性能和占用空间。
  • 定期清理无用、重复的索引。

7. 利用前缀索引和全文索引

  • 对于长字符串字段(如 email、url),可用前缀索引:CREATE INDEX idx_email ON users(email(10));
  • 对于大文本字段,使用 FULLTEXT 全文索引。

七、更多实战案例

案例1:避免索引失效

错误写法:

SELECT * FROM orders WHERE YEAR(order_date) = 2024;

优化写法:

SELECT * FROM orders WHERE order_date >= '2024-01-01' AND order_date < '2025-01-01';

原因: 在索引列上使用函数会导致全表扫描。


案例2:利用联合索引优化排序

原SQL:

SELECT * FROM users WHERE status = 1 ORDER BY create_time DESC;

优化:

CREATE INDEX idx_status_create_time ON users(status, create_time DESC);

效果: 查询和排序都能用到索引,避免 Using filesort。


案例3:覆盖索引提升查询效率

原SQL:

SELECT id, name FROM users WHERE status = 1;

优化:

CREATE INDEX idx_status_id_name ON users(status, id, name);

效果: 查询只用索引,无需回表,Extra 显示 Using index。


案例4:避免索引下推失效

原SQL:

SELECT * FROM users WHERE name LIKE '%abc%';

优化:

SELECT * FROM users WHERE name LIKE 'abc%';

原因: 前缀模糊匹配可用索引,%开头无法用索引。


案例5:合理利用唯一索引

原SQL:

SELECT * FROM users WHERE email = 'test@example.com';

优化:

CREATE UNIQUE INDEX idx_email ON users(email);

效果: 查询效率极高,type 为 const。


案例6:多表关联优化

原SQL:

SELECT * FROM orders o JOIN users u ON o.user_id = u.id WHERE u.status = 1;

优化:

  • orders.user_idusers.id 都加索引
  • users.status 加索引

八、EXPLAIN FORMAT=JSON

MySQL 5.6+ 支持 EXPLAIN FORMAT=JSON,输出更详细、结构化的信息,便于自动化分析。

EXPLAIN FORMAT=JSON SELECT * FROM users WHERE age = 25;

九、常见 Extra 字段含义

  • Using where:通过 where 过滤数据
  • Using index:覆盖索引,无需回表
  • Using temporary:使用了临时表,常见于 group by/order by
  • Using filesort:需要额外排序,性能较差
  • Using join buffer:连接时用到了 join buffer,说明未用到索引

十、SQL 优化常用方法总结

  1. 加索引:为查询条件、排序、分组等常用字段加索引
  2. 优化 where 条件:避免在索引列上使用函数、计算、like '%xx%'等
  3. 覆盖索引:只查询索引中的字段,减少回表
  4. 减少返回行数:用 limit、合理的 where 条件
  5. **避免 select ***:只查需要的字段
  6. 合理设计联合索引:遵循最左前缀原则
  7. 避免临时表和 filesort:优化 group by、order by
  8. 定期用 EXPLAIN 检查 SQL 执行计划,发现并优化慢查询

十一、总结

  • EXPLAIN 是 SQL 优化的利器,能直观展示执行计划
  • 关注 type、rows、Extra 等字段,发现性能瓶颈
  • 通过加索引、优化 SQL、减少全表扫描和 filesort 提升性能
  • 多用 EXPLAINEXPLAIN FORMAT=JSON,结合慢查询日志,持续优化数据库

建议:
每次上线新 SQL,务必用 EXPLAIN 检查执行计划,避免潜在性能隐患!


如需更深入的 SQL 优化案例或遇到具体 SQL 性能问题,欢迎留言交流!

相关文章:

  • 数字化,一个泛化的概念
  • yum命令介绍
  • Javascript 编程基础(4)函数 | 4.3、apply() 与 call() 方法
  • Enhanced RTMP H.265(HEVC)技术规格解析:流媒体协议的新突破
  • 如何支持Enhanced RTMP H.265(HEVC)
  • Linux系统下nslookup命令的基本使用
  • Linux锁和互斥锁
  • 读一本书第一遍是快读还是细读?
  • 【算法专题十五】BFS解决最短路问题
  • 04算法学习_209.长度最小的子数组
  • MCP Server开发使用Pixabay网址搜索图片
  • TypeScript 泛型讲解
  • 《微服务架构设计模式》笔记
  • 基于Matlab建立不同信道模型
  • 鸿蒙HarmonyOS 【ArkTS组件】通用属性-背景设置
  • 腾讯游戏安全与高通合作构建PC端游安全新格局
  • Unity异步加载image的材质后,未正确显示的问题
  • 693SJBH基于.NET的题库管理系统
  • Windows Docker笔记-扩展
  • C++ - 仿 RabbitMQ 实现消息队列(3)(详解使用muduo库)
  • 搬瓦工putty做网站/百度搜索排行榜
  • 网站开发绩效考核与薪酬/网站建设与管理属于什么专业