4. B+树索引原理与面试题:B+树结构、分裂合并、聚簇索引、回表
| 公司侧重点 | 字节跳动(TikTok 存储引擎)、阿里(PolarDB 索引优化)、腾讯云(CynosDB)、华为 GaussDB 均深入考察 B+ 树细节:树高计算、分裂合并伪代码、回表与覆盖索引辨析、InnoDB 与 RocksDB 索引对比。 |
| 面试官画像 | 内核专家 / 高级基础架构师,5 年以上数据库/存储经验,偏好追问“你写的索引真的用了 B+ 树吗?” “分裂时机如何影响并发性能?” 性格严谨,追求底层一致性。 |
本章核心能力:用结构化表达呈现 B+ 树从原理到工程落地的完整逻辑,避免“背八股”,侧重对比、计算和反例。
高频面试问答卡片 · 3 题
卡片 1:B+树结构与选型对比
| 面试问题 | 请详细描述B+树的数据结构,为什么数据库索引选用B+树而不是B树或红黑树? |
|---|---|
| 考察点 | 数据结构理解、异同对比、磁盘IO意识、工程选型思维 |
| 回答框架 |
|
| 简短示例回答 | “B+树每个节点对应一个磁盘页,内节点只存索引,叶子节点存数据且有序链表连接。相比B树,B+树内节点能存放更多索引,树高更低;相比红黑树,B+树扇出高,IO次数少几十倍。这也是InnoDB使用B+树做索引的原因。” |
| 可能追问 |
|
| 避坑提醒 | 不要只说“B+树树高低”就结束,必须给出计算示例(扇出=页大小/键大小)。不要混淆B+树与B*树。不要忽略叶子链表的作用。 |
加分点:现场手算树高——假设16KB页,键8B+指针8B,扇出1024,1亿行数据只需3层(1024³ ≈ 1B)。
卡片 2:B+树分裂与合并机制
| 面试问题 | B+树的分裂和合并过程是怎样的?如何保证索引平衡? |
|---|---|
| 考察点 | B+树维护过程、平衡策略、并发控制意识 |
| 回答框架 |
|
| 简短示例回答 | “假设B+树4阶(最多3个键),插入数据导致节点A有3个键,再插入一个键时触发分裂—创建右兄弟B,将中间键5上提到父节点,左子节点保留1,3,右子节点7,9。若父节点也满则递归分裂。删除导致节点利用率低于1/3时尝试合并,将A与B合并并删除父节点指针。” |
| 可能追问 |
|
| 避坑提醒 | 不要用二叉树分裂逻辑套在B+树上。注意B+树分裂有时是“先插入后分裂”,有时是“先分裂后插入”,不同实现有区别。避免遗漏父节点递归处理。 |
记忆口诀:“满则分,半则合,父递归,层不变”。
卡片 3:聚簇索引、辅助索引与回表
| 面试问题 | 什么是聚簇索引和辅助索引?什么是回表?如何优化回表? |
|---|---|
| 考察点 | 索引组织表、物理存储、查询流程、性能优化 |
| 回答框架 |
|
| 简短示例回答 | “假设表有主键id和辅助索引name,查询SELECT * WHERE name='Alice',先走name索引找到主键id=10,再回聚簇索引找整行。如果只查name和id,则只需name索引本身即可,无需回表—这是覆盖索引。” |
| 可能追问 |
|
| 避坑提醒 | 不要混淆“聚簇索引”和“索引组织表”;注意MyISAM的索引不存储数据行,没有聚簇概念。回表次数不是单次,而是一次辅助索引查询可能多次回表(多行)。 |
高频坑:面试官常问“为什么主键不宜使用UUID?” 答:UUID无序导致聚簇索引频繁页分裂,且占用空间大,辅助索引也变大,增加回表代价。
扩展思考:B+树在分布式数据库中的变体
现代分布式引擎(TiDB、OceanBase)采用LSM-Tree或B+Tree变种,但面试仍会以经典B+树为基准。以下为高阶连贯思考路径:
- B+树与LSM-Tree对比:B+树写放大较小,读友好;LSM-Tree写吞吐高,但读需要合并。
- B+树在分布式中的挑战:分裂/合并需要分布式事务保护,PolarDB使用共享存储避免数据迁移。
- 面试自我反问:如果让你设计一个支持高并发插入的B+树索引,你如何优化分裂时的锁竞争?
面试官期望:不仅知道B+树怎么用,还能讨论“为什么这么设计”以及“如果场景变了怎么调整”。每句话都体现工程权衡。
▲ 高频追问路径图(用于遇到回表问题后进一步深挖)
第4章 · 包含3个高频问答卡片 + 2张SVG(回答框架图 & 追问路径图)