中 基础
MySQL架构与存储引擎#
一句话答案#
MySQL 查询流程:连接器→分析器(语法)→优化器(执行计划)→执行器→存储引擎(InnoDB/MyISAM),插件式架构。
核心要点
B 树(B-tree)vs B+ 树:
| 维度 | B 树 | B+ 树 |
|---|---|---|
| 数据存储 | 非叶子节点也存数据(key + value) | 只有叶子节点存数据,非叶子只存 key |
| 叶子节点 | 不相连 | 双向链表相连 |
| 查询单条记录 | 可能在非叶子节点命中,略快 | 必须到叶子节点,路径固定 |
| 范围查询 | 需要回溯树(中序遍历),效率差 | 叶子链表直接顺序扫描,效率高 |
| 单节点存储 key 数量 | 少(要存 value,占空间) | 多(只存 key,更矮更胖) |
| 磁盘 IO 次数 | 相对多 | 相对少(树更矮,层数少) |
MySQL 选 B+ 树的核心理由:
1. 范围查询高效(MySQL 最常见的查询类型)
WHERE age BETWEEN 18 AND 30→ 找到 18 的叶子节点,沿链表扫描到 30,一次 IO 序列- B 树做范围查询需要多次回溯,效率差
2. 树更矮,IO 次数少
- InnoDB 页大小 16KB,B+ 树非叶子节点只存 key(8 字节 bigint)和指针(6 字节)
- 每页可存约
16384 / (8+6) ≈ 1170个 key - 三层 B+ 树可存约
1170 × 1170 × 16 ≈ 2200 万条数据,只需 3 次磁盘 IO
3. 查询性能稳定
- B+ 树所有数据在叶子层,任何查询的路径长度相同,性能稳定
- B 树数据分布不均,性能抖动
4. 叶子层顺序 IO,友好磁盘预读
- 全表扫描时叶子链表顺序读,接近顺序 IO,比 B 树的随机访问快得多
面试回答(2分钟版)
MySQL 采用分层架构,一条 SQL 的执行要经过连接器、分析器、优化器、执行器,最终调用存储引擎获取数据。存储引擎是插件式的,默认 InnoDB。MySQL 选择 B+ 树作为索引结构主要有三个原因:第一,B+ 树只有叶子节点存数据且叶子通过双向链表连接,范围查询时找到起点后沿链表顺序扫描即可,效率远高于 B 树的回溯遍历;第二,非叶子节点只存 key 不存数据,一个 16KB 的页可以存约 1170 个指针,三层 B+ 树就能存两千多万条记录,只需三次磁盘 IO;第三,所有查询都要走到叶子层,路径长度一致,性能稳定无抖动。另外 MySQL 8.0 已经移除了查询缓存,因为表级别的失效粒度太粗,在写多读多场景下命中率极低反而增加开销。
追问与易错
追问方向:
- “查询缓存为什么被移除?”→ 查询缓存以表为粒度失效,任何对表的写操作都会使该表所有缓存失效;在写多读多场景下命中率极低,反而增加加锁和失效开销,MySQL 8.0 彻底移除
- “连接线程和线程池关系?”→ 默认每个客户端连接分配一个独立线程(one-thread-per-connection),连接多时线程数暴增;线程池(Thread Pool)复用固定数量线程处理请求,减少上下文切换,企业版或 Percona 版支持
- “Plugin 架构的好处?”→ 存储引擎以插件形式接入,Server 层与引擎层接口解耦;可以按需选择不同引擎(InnoDB 事务型、Memory 临时表),也方便第三方开发新引擎而不改 Server 代码
易错点:
- ❌ MySQL 8.0 还有查询缓存——已移除
- ❌ 混淆 Server 层和引擎层