Yihui’s Blog

MySQL查询执行流程是怎样的?查询优化器是如何工作的?

日期:2026-09-27
标签:#面试 #MySQL #数据库
难度:中等
来源:牛面 MySQL 题库
答案说明:独立整理(站内题目标记为 VIP,未读取会员答案)

一句话答案

MySQL解析SQL后由优化器选择访问路径和连接顺序,再由执行器调用存储引擎获取数据并返回结果。

面试口语版(约 60 秒)

客户端发来 SQL 后,服务器解析并校验对象权限与语义,优化器根据索引和统计信息挑访问路径、连接顺序等计划,执行器按计划读取存储引擎数据,完成过滤、聚合、排序并返回结果。优化器是基于成本估算的选择器,不保证每次选到现实中最快的计划,所以我会先用 EXPLAIN 看估算,再用 EXPLAIN ANALYZE 核对真实行数和耗时。

原理拆解与场景

flowchart LR
  A[SQL] --> B[解析与检查]
  B --> C[成本优化器]
  C --> D[执行器]
  D --> E[InnoDB 索引与数据页]
  E --> F[结果]

例如 SELECT * FROM orders WHERE user_id=42 ORDER BY created_at DESC LIMIT 20,复合索引 (user_id, created_at) 可能同时缩小扫描并支持顺序读取;若只有 status 索引,低选择性可能使它不划算。

关键边界与工程取舍

“逻辑执行顺序”是理解结果的模型,物理执行可重排、下推、提前停止。统计信息过期、数据倾斜和参数分布变化会造成估算偏差;先记录实际计划和工作负载,再考虑 ANALYZE TABLE、索引调整或必要时提示。EXPLAIN ANALYZE 会真正执行查询,线上使用要谨慎。

面试官递进追问

1. 优化器为什么不一定选择有索引的路径?

参考答案: 有索引只说明存在一种候选路径,不代表代价最低。过滤条件命中大部分行且查询很多非索引列时,二级索引查找加大量回表可能比顺序扫描更贵;表很小、排序需求不同也会影响选择。还要先区分“索引可用但没选”和“表达式、类型转换、排序规则等使索引难以利用”。我会看候选索引、实际选用路径、预计扫描量与回表成本,再核对统计信息,不会只凭出现全表扫描就强制索引。

2. 估算行数与实际行数差距大说明什么?

参考答案: 差距大说明优化器对该节点的基数或过滤率估计不准,可能来自统计信息陈旧、采样误差、热点值倾斜、多列相关性,或表达式使选择率难以估算。先确认比较的是同一节点、同一组参数和相同循环口径,再找偏差最早出现的位置,因为前面的误差会放大后续连接成本。可按问题更新索引统计、为适合的列收集直方图,或调整索引与 SQL,再用相同负载复测。ANALYZE TABLE 不是万能修复,多列相关性等限制仍可能存在。优化器统计信息

3. 如何验证复合索引同时帮助过滤和排序?

参考答案: 以 WHERE user_id=42 ORDER BY created_at DESC LIMIT 20 为例,检查 (user_id, created_at) 是否用于定位该用户,再看计划是否通过索引顺序读取且没有额外 Sort 节点或 Using filesort。普通升序索引可以反向扫描满足单一降序要求,不必一见 DESC 就重建索引。再用 EXPLAIN ANALYZE 比较扫描行数、返回行数和耗时,确认确实能较早停止;不能只看 key 字段。若还有低命中率的残余过滤,可能仍扫描很多记录;若需要稳定分页,再增加唯一键作为排序并列时的裁决条件,并核对索引顺序是否支持。ORDER BY 优化

自测

  • 合上笔记,用 60 秒复述一句话结论、一个例子和一个边界。
  • 完成第 3 个追问,写出你会核对的 SQL、指标或故障证据。

延伸阅读

参考资料

以 MySQL 8.4 为版本基准;官方资料核对日期:2026-09-27。

Maintained by · YihuiEdit on GitHub

Keep reading

View all posts