第一讲:一条 SQL 查询语句是如何执行的
总览图示
MySQL 查询的执行流程可以大致分为以下步骤(如图所示):
- 连接器(Connection)
- 查询缓存(Query Cache,MySQL 8.0 已废弃)
- 分析器(Parser)
- 优化器(Optimizer)
- 执行器(Executor)
整个 MySQL 架构分为 Server 层 与 存储引擎层(Storage Engine):
Server 层 | 存储引擎层 |
---|---|
连接器、查询缓存、分析器、优化器、执行器、内置函数、触发器、视图、存储过程等 | 数据的实际存储与读取,支持 InnoDB、MyISAM、Memory 等引擎 |
一、连接器(Connector)
负责管理客户端连接、验证身份、权限检查及连接生命周期维护。
bash
mysql -h<ip地址> -P<端口> -u<用户名> -p
工作流程:
- 验证用户身份:连接后输入密码,系统校验用户名/密码是否正确。
- 权限校验 :认证通过后,系统会从权限表读取用户权限。更改权限后需重新连接才能生效。
- 连接状态管理 :长时间不操作,连接会因
wait_timeout
参数超时自动断开(默认8小时)。 - 长连接问题 :
- 长连接可减少连接频率,但可能导致内存膨胀。
- 推荐措施:
- 定期断开或重置连接。
- 使用
mysql_reset_connection
(MySQL 5.7+)释放连接资源,但不需重新验证权限。
二、查询缓存(Query Cache)
说明:MySQL 8.0 已彻底移除查询缓存功能,以下内容适用于旧版本。
工作原理:
- 执行
SELECT
语句前,先检查是否有完全相同的 SQL 已执行过并缓存在内存中(key=语句文本,value=结果集
)。 - 命中缓存则直接返回结果,跳过后续步骤。
- 未命中则执行后续流程,并将结果缓存。
使用建议:
-
查询缓存对动态更新频繁的表几乎无效,一旦表被修改,与其相关的所有缓存都会失效。
-
只适合查询频率高、更新频率低的静态表(如配置表)。
-
推荐按需使用:
sqlSELECT SQL_CACHE * FROM T WHERE ID=10;
三、分析器(Parser)
将 SQL 文本转换为数据库能识别的结构形式(语法分析 + 词法分析)。
功能:
- 词法解析:识别关键词、表名、字段名等组成部分。
- 语法检查:验证 SQL 是否符合语法规范。
示例:
sql
elect * from t where ID=1;
报错信息:
bash
ERROR 1064 (42000): You have an error in your SQL syntax;
错误提示会定位到第一个出错的位置 ,关注提示中的 use near
即可定位错误代码段。
四、优化器(Optimizer)
SQL 有多种执行方式,优化器选择最优执行路径。
功能:
- 决定使用哪个索引(如多索引场景)
- 决定多表
JOIN
顺序(不同顺序会影响执行效率)
示例:
sql
SELECT * FROM t1 JOIN t2 USING(ID) WHERE t1.c=10 AND t2.d=20;
两种执行方案:
- 先查
t1.c=10
,再连表t2
判断t2.d=20
- 先查
t2.d=20
,再连表t1
判断t1.c=10
优化器会选择代价(成本)最低的执行路径。
五、执行器(Executor)
执行器按优化器选择的方案实际执行查询语句。
流程:
- 权限检查:再次验证用户是否对该表有查询权限。
- 调用引擎接口:根据是否有索引,选择不同的数据读取方式。
无索引执行流程:
sql
SELECT * FROM T WHERE ID=10;
执行器会:
- 顺序读取每一行(全表扫描)
- 判断是否满足
ID=10
条件 - 满足则加入结果集
- 返回所有结果集给客户端
有索引执行流程:
- 使用索引快速定位满足条件的记录。
- 使用"满足条件的第一行" → "下一行"的迭代接口。
- 查询效率显著提升。
在慢查询日志中可以看到 Rows_examined
字段,即执行过程中扫描的数据行数。