字节真实面经:以Mysql为例,讲一下一条SQL的执行过程和原理!

2025-12-12 0 366

一条 SQL 的奇幻漂流:从敲下回车到结果返回,MySQL 到底经历了什么?

这恐怕是很多后端同学第一次被“SQL 执行流程”拷问灵魂的瞬间 。
明明平时写 SQL 写得飞起,什么 SELECT * FROM user WHERE id = 1; 手到擒来,
可真让你说清楚它从 「回车键」「结果返回」 的全过程,
十有八九都是一脸懵圈。

今天我们就来当一回数据库侦探 ‍,
跟着这条 SQL 一起,深入 MySQL 的地底世界。
顺便也看看它的老对手 PostgreSQL 是怎么干这事的。


一条 SQL 的旅程,从客户端到结果集

假设我们执行这样一句 SQL:

SELECT name, age FROM users WHERE city = \'Shanghai\' ORDER BY age DESC LIMIT 10;

这句话从敲下回车的那一刻起,其实会经历 「七个阶段」

别急,我们一个一个扒开看。


1. 连接管理器(Connection Manager)

MySQL 是个典型的 「客户端/服务器架构」。 当你通过客户端(比如 Navicat、Go 的 database/sql)发起连接时, MySQL 会先进入 「连接管理阶段」

「MySQL」 使用线程池模型,一个连接对应一个线程。 「PostgreSQL」 传统上是一个连接一个进程(也因此多连接下开销更大)。

连接建立好后,MySQL 会先验证账号密码、权限等。 连接成功后,你就能愉快地发送 SQL 了。

小知识点: 「MySQL 8.0 引入了连接池 plugin,可以减少线程开销。」 而 PostgreSQL 则常用第三方连接池(如 pgBouncer)来减压。


2. 查询缓存(Query Cache)——曾经的“短命天才”

MySQL 曾经有一个 「Query Cache」, 如果你发的 SQL 在缓存里有一模一样的结果,它直接返回 。

问题是,只要表中有一行数据被更新, 相关缓存就全部失效 。 高并发场景下,这反而拖慢了性能。

于是从 MySQL 8.0 开始,「Query Cache 被彻底移除」。 而 PostgreSQL 则一直没有内建 Query Cache, 因为它更倾向于用 「共享缓冲区 + 执行计划缓存」 来提速。


3. 解析器(Parser)——把 SQL 拆成语法树

解析器的工作就像语文老师批作文。 它要判断这句话语法对不对, 然后把 SQL 拆成一个内部可理解的结构:「抽象语法树(AST)」

举个例子 我们的 SQL:

SELECT name, age FROM users WHERE city = \'Shanghai\' ORDER BY age DESC LIMIT 10;

会被解析成一棵树结构(简化版):

Select
 ├── Columns: [name, age]
 ├── From: users
 ├── Where: city = \'Shanghai\'
 ├── OrderBy: age DESC
 └── Limit: 10

PostgreSQL 同理,也会生成 AST,但它在此阶段就做了更多语义检查(比如字段是否存在)。


4. 优化器(Optimizer)——SQL 的灵魂工程师

到这里是重头戏 。 优化器的任务是:

比如上面的查询,优化器要考虑:

  • 要不要用索引?哪个索引?
  • 是先过滤 city 还是先排序?
  • 是否可以走覆盖索引?
  • 是否能用回表、临时表、文件排序?

MySQL 使用 「基于代价的优化器(Cost-Based Optimizer)」。 它会估算每种执行计划的代价(I/O、CPU、行数等),然后选最优。

而 PostgreSQL 则以优化器强悍著称: 它支持更多的 join 策略(如 Hash Join、Merge Join) 还能利用统计信息动态决定 plan。

小技巧: 执行前可以通过 EXPLAIN 看执行计划。 比如:

EXPLAIN SELECT name, age FROM users WHERE city = \'Shanghai\' ORDER BY age DESC LIMIT 10;

这会告诉你是否使用了索引、扫描方式(全表/索引)、排序代价等。

「那怎么判断是否使用了索引?」

执行结果一般会有一列叫 type 和一列叫 key

字段 含义
type 表示访问类型(性能从好到坏:system > const > eq_ref > ref > range > index > ALL)
key 表示使用的索引名,如果是 NULL 则说明没用索引

例子一:

type: range, key: idx_city

说明走了索引扫描(利用了 city 索引)

例子二:

type: ALL, key: NULL

说明是全表扫描(MySQL 从头到尾扫一遍表的数据页)

一般来说,全表扫描 (ALL) 性能最差,尤其是大表上。 而索引扫描(range / ref)表示查询条件命中索引,效率更高。 可以用 EXPLAIN ANALYZE(MySQL 8.0.18+)进一步看到真实执行时间。


️ 5. 执行器(Executor)——执行计划落地的地方

优化器决定了“怎么干”,执行器就负责“真干”。 它会按照优化器的 plan,调用底层的存储引擎 API。

比如说它要从表里取数据,就会调用:

engine.read(\"users\", condition)

(当然底层不是真的 Go 哈,这只是方便理解 )

每读一行,就判断 city == \'Shanghai\', 符合条件的就放进结果集,最后排序、截取前 10 条。


️ 6. 存储引擎层(Storage Engine Layer)

这是 MySQL 最有“灵魂分裂感”的部分 。 因为不同表,可以有不同的存储引擎!

最常见的当然是 「InnoDB」

InnoDB 负责的数据层逻辑包括:

  • 数据页缓存(Buffer Pool)
  • 索引(B+ Tree)
  • 事务(Redo/Undo 日志)
  • 行锁机制

而 PostgreSQL 没有“存储引擎”这个概念, 它的存储层和执行层是紧耦合的。 但它在 「MVCC(多版本并发控制)」 上比 MySQL 更纯粹:每次更新会产生新版本,而不是回滚段。


7. 返回结果(Result Set)

当执行器拿到结果集后, 会通过网络协议一批一批地返回给客户端。

你以为这一步就结束了? 其实不是

客户端驱动(比如 Go 的 sql.Rows) 还会逐行读取结果、反序列化成结构体。 这就是为什么一次性查询 10 万条时,客户端内存会爆炸的原因 。


总结:MySQL 执行 SQL 的完整图示

下面这张图就是整条 SQL 的生命周期:

[客户端]
   │
   ▼
[连接器][查询缓存(已废弃)][解析器][优化器][执行器][存储引擎]
   │                                                    │
   └────────────────────────────── 结果集返回 ───────────┘

延伸思考

  1. PostgreSQL 的优化器比 MySQL 强在哪里? 更智能的执行计划评估 + 更丰富的 join 策略。
  2. 为什么深分页 (LIMIT 1000000, 10) 慢? 因为执行器仍要扫描前一百万行,只是丢掉不用的部分。 (这也是上一篇我们讲过的优化点 )
  3. 为什么有时候 EXPLAIN 看似走了索引却仍然慢? 因为数据分布、索引选择、排序代价都可能抵消索引优势。

小结一下(怕你看累了 )

阶段 关键职责 对应 PostgreSQL 对比
连接器 线程管理、权限校验 进程模型,性能更稳
查询缓存 8.0 已废弃 无,靠 plan cache
解析器 生成语法树 同理,但语义更严
优化器 选最优执行计划 更智能的代价模型
执行器 调用引擎执行 更统一的执行框架
存储引擎 InnoDB 事务、索引、锁 内置 MVCC,无引擎层
返回结果 网络传输 同理

最后的思考题

记住,懂执行顺序不仅是为了背面试题, 更是为了当系统慢时,能知道该“查哪一层”。

比如:

  • 慢在优化器:可能统计信息不准;
  • 慢在执行器:可能索引没生效;
  • 慢在存储层:可能 I/O 或锁冲突;
  • 慢在客户端:可能网络或反序列化太重。

只有理解了整个流程,才能真正玩转数据库。 别忘了,「SQL 不只是数据语言,它是系统协作的艺术。」



「技术有道|用故事讲技术,让底层原理不再枯燥」 VX搜索Tech有道 , 获取更多资料和真实面经

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

申明:本文由第三方发布,内容仅代表作者观点,与本网站无关。对本文以及其中全部或者部分内容的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。本网发布或转载文章出于传递更多信息之目的,并不意味着赞同其观点或证实其描述,也不代表本网对其真实性负责。

左子网 编程相关 字节真实面经:以Mysql为例,讲一下一条SQL的执行过程和原理! https://www.zuozi.net/35682.html

常见问题
  • 1、自动:拍下后,点击(下载)链接即可下载;2、手动:拍下后,联系卖家发放即可或者联系官方找开发者发货。
查看详情
  • 1、源码默认交易周期:手动发货商品为1-3天,并且用户付款金额将会进入平台担保直到交易完成或者3-7天即可发放,如遇纠纷无限期延长收款金额直至纠纷解决或者退款!;
查看详情
  • 1、描述:源码描述(含标题)与实际源码不一致的(例:货不对板); 2、演示:有演示站时,与实际源码小于95%一致的(但描述中有”不保证完全一样、有变化的可能性”类似显著声明的除外); 3、发货:不发货可无理由退款; 4、安装:免费提供安装服务的源码但卖家不履行的; 5、收费:价格虚标,额外收取其他费用的(但描述中有显著声明或双方交易前有商定的除外); 6、其他:如质量方面的硬性常规问题BUG等。 注:经核实符合上述任一,均支持退款,但卖家予以积极解决问题则除外。
查看详情
  • 1、左子会对双方交易的过程及交易商品的快照进行永久存档,以确保交易的真实、有效、安全! 2、左子无法对如“永久包更新”、“永久技术支持”等类似交易之后的商家承诺做担保,请买家自行鉴别; 3、在源码同时有网站演示与图片演示,且站演与图演不一致时,默认按图演作为纠纷评判依据(特别声明或有商定除外); 4、在没有”无任何正当退款依据”的前提下,商品写有”一旦售出,概不支持退款”等类似的声明,视为无效声明; 5、在未拍下前,双方在QQ上所商定的交易内容,亦可成为纠纷评判依据(商定与描述冲突时,商定为准); 6、因聊天记录可作为纠纷评判依据,故双方联系时,只与对方在左子上所留的QQ、手机号沟通,以防对方不承认自我承诺。 7、虽然交易产生纠纷的几率很小,但一定要保留如聊天记录、手机短信等这样的重要信息,以防产生纠纷时便于左子介入快速处理。
查看详情

相关文章

猜你喜欢
发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务