在mysql数据库的日常开发与运维中,查询语句的执行效率直接决定了业务系统的响应速度,当遇到慢查询问题时,分析查询执行计划是最直接有效的定位方式。通过执行计划可以清晰看到mysql优化器对一条SQL语句的执行规划,包括表的访问顺序、索引使用情况、数据扫描范围等关键信息。

什么是mysql查询执行计划
查询执行计划是mysql优化器针对输入的SQL语句生成的一套执行方案,它描述了mysql会按照什么顺序访问表、使用哪些索引、预计扫描多少行数据等内容。我们可以通过EXPLAIN命令来获取任意SELECT语句的执行计划,从而判断SQL语句的执行效率是否符合预期。
如何获取查询执行计划
获取执行计划的操作非常简单,只需要在要分析的SELECT语句前加上EXPLAIN关键字即可,语法格式如下:
-- 基础用法,分析单条查询语句 EXPLAIN SELECT * FROM user WHERE age > 18; -- 也可以分析带关联查询的语句 EXPLAIN SELECT u.name, o.order_no FROM user u LEFT JOIN order o ON u.id = o.user_id WHERE u.status = 1;
如果是mysql 8.0及以上版本,还支持使用EXPLAIN ANALYZE获取更详细的执行信息,包括每个步骤的实际执行时间和返回行数,不过该命令会实际执行SQL语句,需要注意对线上数据的影响。
执行计划核心字段解析
执行EXPLAIN命令后会返回一张结果表,每个字段都有特定的含义,下面逐一介绍常用的核心字段:
| 字段名 | 含义说明 |
|---|---|
| id | 查询的序列号,表示查询的执行顺序,id值越大越先执行,id相同则从上到下执行 |
| select_type | 查询的类型,常见的有SIMPLE(简单查询,不含子查询或联合查询)、PRIMARY(最外层的查询)、SUBQUERY(子查询)等 |
| table | 当前查询访问的表名 |
| type | 表的访问类型,性能从好到坏依次为system > const > eq_ref > ref > range > index > ALL,其中ALL表示全表扫描,需要重点优化 |
| possible_keys | mysql可能使用的索引列表 |
| key | mysql实际使用的索引,如果为NULL则表示没有使用索引 |
| rows | mysql预计需要扫描的行数,该值越小说明查询效率越高 |
| Extra | 额外信息,常见的有Using index(覆盖索引,不需要回表)、Using where(使用了where过滤)、Using filesort(需要额外排序,性能较差)、Using temporary(使用了临时表,性能较差) |
通过执行计划分析查询性能的常见场景
场景1:判断索引是否生效
当我们为表的字段创建索引后,需要确认查询是否真正使用了索引,此时可以通过执行计划的key字段判断。如果key字段显示我们创建的索引名,说明索引生效;如果为NULL,则说明索引没有生效,可能需要调整查询条件或者索引结构。
比如我们为user表的age字段创建了普通索引idx_age,执行以下查询:
-- 索引生效的情况,key会显示idx_age EXPLAIN SELECT * FROM user WHERE age = 20; -- 索引不生效的情况,对索引字段使用函数会导致索引失效,key为NULL EXPLAIN SELECT * FROM user WHERE YEAR(create_time) = 2024;
场景2:判断是否存在全表扫描
全表扫描(type为ALL)是查询性能差的常见原因,尤其是大表的全表扫描会消耗大量数据库资源。如果执行计划中type字段为ALL,且rows字段数值很大,就需要考虑优化:要么为查询条件添加合适的索引,要么调整查询条件缩小扫描范围。
场景3:判断是否需要优化排序或临时表
如果执行计划的Extra字段出现Using filesort或者Using temporary,说明查询需要额外的排序操作或者使用了临时表,这类操作的性能通常较差。此时可以考虑为排序字段或者分组字段创建合适的索引,避免mysql进行额外的排序或临时表操作。
执行计划分析注意事项
- 执行计划中的rows是预估值,不是实际扫描行数,实际执行时可能会有偏差
- 分析执行计划时需要结合实际的表数据量,小表的ALL访问类型可能也不会有明显性能问题
- 不要过度依赖执行计划,复杂查询可以结合实际的执行时间、慢查询日志综合判断
- 修改索引或者SQL语句后,需要重新分析执行计划确认优化效果
掌握mysql查询执行计划的分析方法,能够帮助开发者快速定位SQL性能问题,针对性地进行索引优化和SQL改写,有效提升数据库的整体运行效率。日常开发中建议在编写复杂查询语句后,先通过执行计划确认性能是否符合要求,再上线到生产环境。