MySQL篇5:MySQL深度揭秘——MySQL 执行计划分析与 SQL 优化最佳实践

MySQL 性能优化的起点,往往是读懂执行计划定位慢 SQL 原因,再根据问题对应地进行优化。本文整理了执行计划的核心知识,以及在实际项目中可直接使用的 SQL 优化方法,为开发人员提供一套完整的调优思路。


一、执行计划分析(EXPLAIN)

1. 什么是执行计划?

简单来说就是知道我们这个sql到底干了什么,是怎么干的。

执行计划(Execution Plan)是 MySQL 查询优化器对 SQL 语句进行分析后,给出的具体执行方式

通过执行计划,我们能够了解到:

  • 查询的表访问顺序

  • SQL 使用了哪些索引、哪些未使用

  • 扫描了多少行数据

  • 使用了什么连接方式

  • 是否发生排序、临时表

  • 查询大致的成本和效率

优化 SQL 的第一步,就是先读懂执行计划。


2. EXPLAIN 输出的 12 列含义

执行计划总共有 12 列核心字段,含义如下:

列名 含义
id SELECT 的执行顺序标识。id 越大优先级越高。id 相同则从上往下执行。
select_type 查询类型(普通查询、子查询、UNION 等)。
table 当前访问的表名。
partitions 匹配到的分区(未分区则为 NULL)。
type 表访问方式,性能从好到差依次为 system > const > eq_ref > ref > range > index > ALL。
possible_keys 可能会用到的索引。
key 实际使用的索引。
key_len 使用的索引长度(以字节为单位)。
ref 与索引比较的列或常量。
rows 估计需要扫描的行数。
filtered 条件过滤后剩余行数的百分比。
Extra 附加执行信息,例如排序、临时表等。

下面分析其中

3. select_type 常见类型

简单来说它告诉你这条 SELECT 在整条 SQL 里的"身份"。

  • SIMPLE:简单查询,不包含子查询或 UNION。

  • PRIMARY:最外层 SELECT。

  • SUBQUERY:子查询中的第一个 SELECT。

  • UNION:UNION 中的第二个及后续 SELECT。

  • DERIVED:FROM 子查询(会被物化成临时表)。

  • UNION RESULT:UNION 合并结果。


4. type(访问类型)

简单来说type 体现了表的访问方式,是效率的核心,越靠近左边越快,ALL 最慢。

访问方式从最优到最差依次为:

sql 复制代码
system > const > eq_ref > ref > range > index > ALL

常见解释:

  • const:主键或唯一索引等值查询,只返回一行。

  • eq_ref:关联查询时被关联表的唯一匹配。

  • ref:普通索引等值查询,可能返回多行。

  • range:范围查询使用索引(BETWEEN、>、< 等)。

  • index:扫描整个索引树。

  • ALL:全表扫描,是最慢的方式。


5. Extra 信息

简单来说它告诉你 SQL 过程中有没有临时表、额外排序、是否覆盖索引等。

Extra 中的提示对判断是否需要优化非常关键:

  • Using filesort

    排序无法使用索引,MySQL 需要额外排序(性能较差)。

  • Using temporary

    使用了临时表,常见于 ORDER BY、GROUP BY。

  • Using index

    使用了覆盖索引,不需要回表查询,性能好。

  • Using where

    使用 WHERE 过滤,但不一定使用索引。

  • Using join buffer

    关联查询时被驱动表未走索引,需要 join 缓存。

其中 Using filesort / Using temporary 大多数情况下意味着 SQL 仍有优化空间。


二、SQL 优化最佳实践

SQL 优化的核心流程是:

sql 复制代码
慢 SQL 定位 → 慢 SQL 分析 → 问题原因 → 对应优化方案

1. 慢 SQL 定位

开启慢查询日志(slow query log),记录执行时间超过一定阈值的 SQL。

通过慢日志可以快速找到需要优化的语句。


2. 慢 SQL 分析方向

慢 SQL 常见原因:

  1. 数据量太大

  2. 并发量太高

  3. 索引缺失或使用不当

  4. SQL 语句书写不合理

  5. 表结构设计问题

  6. 业务需求设计不合理

  7. 数据库服务器性能瓶颈

在优化之前,先判断 SQL 是由于逻辑问题、索引问题还是架构瓶颈导致。


三、索引优化实践

1. 控制索引数量

  • 单表不建议超过 5 个索引。

    索引越多,维护成本越高,优化器的选择成本也越高。

2. 联合索引的顺序

  • 区分度最高的字段放在最前

  • 最常作为查询条件的字段放前面

因为联合索引遵循 最左前缀法则

3. where/order/group 的索引使用

如果 where、order by、group by 中包含多个字段,建议建立联合索引而不是多个单列索引。

例如:

sql 复制代码
SELECT age, city, name 
FROM user 
WHERE age = 20 AND city = 'Beijing' 
ORDER BY name;

最优索引是:

sql 复制代码
(age, city, name)

因为 name 在联合索引中已经天然有序,可以避免 filesort。


四、SQL 语句优化

1. 不要使用 SELECT *

  • 增加解析与网络开销

  • 会导致无法使用覆盖索引

2. 多表 join:小表驱动大表

优先让较小的数据集作为驱动表

避免大表驱动小表造成巨大的 join buffer 负担。

3. union 替换 union all(视情况)

  • union 会去重,消耗更多 CPU

  • 如果业务允许重复,优先使用 union all


五、表结构优化

1. 常一起使用的字段放在同一张表

避免频繁 join。

2. 合理使用反范式

为了性能允许冗余字段,例如把频繁 join 的字段冗余到主表。

3. 使用更小的数据类型

数字使用 INT

时间使用 DATETIME/TIMESTAMP 或整型时间戳

避免使用 VARCHAR 过大

避免 TEXT/BLOB(必要时拆分扩展表)

4. 尽量避免 NULL

由于:

  • 需要额外的 NULL 标记位

  • 影响索引存储与比较

  • 聚合操作需要特殊处理


六、业务层优化

许多慢 SQL 根源不是 SQL 本身,而是业务需求问题:

  • 分页查第 1000 页,本身不合理

  • 某些报表可以提前计算而不是实时计算

  • 热点数据应该缓存,而不是实时读库

优化往往需要业务参与,而不是仅靠开发。


七、架构层优化

1. 读写分离

将读和写拆到不同实例,提高并发能力。

2. 分库分表

降低单表数据量,提升查询效率,但维护成本更高。

3. 使用缓存(Redis)

热点数据、高频查询尽量缓存,减少数据库压力。

4. 使用分布式数据库(如 TiDB)

适用于海量数据、高并发场景。


总结

本文从执行计划分析到 SQL、索引、表结构、业务、架构多方面,总结了完整的 MySQL 优化体系。核心思想始终是:

  • 先根据执行计划定位问题

  • 再有针对性地从 SQL、索引、业务或架构层面进行改进

相关推荐
youxiao_9041 分钟前
Mysql 备份与还原
数据库·mysql
友友马42 分钟前
『MySQL - 进阶』存储过程(上):核心概念、变量体系与流程控制
android·数据库·mysql
zhougl99643 分钟前
学习-深入学习SQL语句
数据库·sql·学习
('-')43 分钟前
《从根上理解MySQL是怎样运行的》第二十三章笔记
数据库·笔记·mysql
Mr.徐大人ゞ44 分钟前
13.MHA 常用问题
mysql
LSL666_44 分钟前
云服务器安装MySQL
运维·服务器·mysql
卿雪1 小时前
MySQL【数据类型】:CHAR 和 VARCHAR 的对比、VATCHAR(n) 和 INT(n) 里的 n 一样吗?
android·java·数据库·python·mysql·adb·golang
麦聪聊数据1 小时前
Web架构如何打通从SQL 脚本到API 服务的全链路追踪?
数据库·sql·架构
范小多1 小时前
mysql实战 C# 访问mysql(连载三)
数据库·mysql·oracle·c#