Sql查询的执行过程是什么
1. 总体链路:从客户端到结果集
以 MySQL 为例,一条查询从发出到返回,大致经过:
- 建立连接与会话(连接器/权限/参数)。
- SQL 解析(词法/语法)生成语法树。
- 预处理(语义校验、权限校验、表/列解析)。
- 优化器生成并选择执行计划(索引选择、JOIN 顺序、访问方法)。
- 执行器按计划驱动存储引擎读取数据。
- 结果集返回客户端(可能分批拉取)。
2. SQL 层:解析与预处理
2.1 解析(Parser)
解析阶段会把 SQL 变成内部结构(语法树),并做基础规范化处理。
2.2 预处理(Preprocess)
预处理阶段会做:
- 表/列是否存在、类型是否匹配。
- 权限校验。
- 视图展开、子查询的一些改写(视优化器策略而定)。
3. 优化器:执行计划如何选择
优化器的目标是:选择“代价最低”的计划(cost-based),核心决策包括:
- 走哪个索引(单列/联合索引、是否覆盖索引)。
- 访问方法(全表扫、范围扫、点查、索引合并等)。
- JOIN 顺序与 JOIN 算法(嵌套循环为主,部分场景有哈希连接等能力)。
- 是否需要额外排序(filesort)或临时表。
计划选择强依赖统计信息(索引基数、直方图等)。统计信息不准时,可能出现“看起来应该走索引却没走”的现象。
4. 执行器与存储引擎:数据怎么被读出来
执行阶段通常表现为“迭代器模型”:执行器按照计划一步步向存储引擎取行,做过滤、投影、聚合等操作。
以 InnoDB 为例,实际读取会涉及:
- Buffer Pool:命中则直接从内存返回,否则读取磁盘页。
- B+ 树索引:定位记录所在页与行。
- MVCC/锁:决定能否读到某版本、是否需要加锁(快照读/当前读)。
5. 如何验证与排查
5.1 EXPLAIN 看计划
EXPLAIN SELECT * FROM t WHERE a = 1 AND b > 10 ORDER BY c;
重点字段:
type:访问方式(从好到差通常是const/ref/range/index/all)。key:最终选择的索引。rows:预估扫描行数。Extra:是否Using index、Using filesort、Using temporary。
5.2 结合慢日志与统计信息
执行计划不稳定或突然变慢时,通常要结合:
- 慢查询日志(定位 SQL 与耗时)。
- 统计信息是否过旧(触发重新分析)。
- Buffer Pool 命中率与 I/O 压力。