mysql中解析器与查询执行器的作用与流程

来源:这里教程网 时间:2026-02-28 20:49:53 作者:

MySQL 查询解析器干了什么

解析器负责把

SELECT * FROM users WHERE id = 1
这类文本 SQL 转成内部可识别的语法树(parse tree),不是直接执行,也不做权限或语义检查。

它只管三件事:词法分析(切分关键字、标识符、数字)、语法分析(验证是否符合 MySQL 语法规则)、生成初始语法树。

遇到
ORDER BY
写成
ORDERY BY
,解析器立刻报错
ERROR 1064 (42000)
,不进下一步
SELECT a+b FROM t
中的
a+b
在这步只是被记为一个表达式节点,不计算值,也不查字段是否存在
解析器不关心表有没有索引、用户有没有权限——这些是后续模块的事

查询执行器真正干活的顺序

执行器拿到优化器输出的执行计划后,才开始调存储引擎接口取数据。它不解析 SQL,也不决定怎么查,只负责“按指令一步步跑”。

典型流程:

open table → find index or full scan → read rows → filter WHERE → sort if needed → send result

即使
WHERE id = 1
有索引,执行器仍要调用
ha_innobase::index_read()
或类似接口,由 InnoDB 层完成实际定位
如果
WHERE
条件里有函数,比如
WHERE YEAR(created_at) = 2023
,执行器会在读出每行后调用函数计算,无法跳过无关行(除非函数能下推到引擎层)
执行器会反复调用
handler::rnd_next()
handler::index_next()
,直到返回
HA_ERR_END_OF_FILE

为什么有时 explain 显示用了索引,但慢查询日志里 still doing 'Sending data'

因为

Sending data
状态在执行器阶段,表示正在从引擎读取并组装结果集——哪怕索引查找很快,但匹配行数巨大、或者需要回表、或者涉及临时表排序,都会卡在这步。

EXPLAIN
type: ref
只说明索引查找方式,不代表最终扫描/返回行数少
执行器对每一行都要做字段提取、类型转换、字符集处理,大字段(如
TEXT
)或宽表会让这步变慢
如果查询含
GROUP BY
且无法利用索引排序,执行器会建内部临时表+文件排序,
Creating sort index
也会计入此状态

parser 和 executor 之间还有哪些关键中间环节

解析器输出语法树后,不会直接交给执行器。中间至少经过:预处理器(检查表/列是否存在)、优化器(重写查询、选择索引、生成执行计划)。

预处理器发现
SELECT * FROM nonexistent_table
,报错
ERROR 1146 (42S02)
,比解析器晚、比优化器早
优化器可能把
SELECT a FROM t WHERE a > 1 AND a  改写成 <code>SELECT a FROM t WHERE a BETWEEN 2 AND 9
,执行器看到的是改写后的计划
执行器拿到的是
JOIN_TAB
数组和访问方法(
JT_ALL
,
JT_INDEX_SCAN
等),不是原始 SQL

真正容易被忽略的是:解析器和执行器之间没有缓存,每次查询都重走全流程;而查询缓存(已弃用)或 Plan Cache(8.0.22+ 的

query_cache_type=OFF
下不可用)影响的是更上层,跟这两个模块本身无关。

相关推荐