★ MySQL 为什么选用 B+Tree 作为索引结构?

结论先行:InnoDB 索引底层是 B+Tree。选它而非哈希、红黑树或 B 树,是因为 B+Tree 层数矮、叶子节点有序串联,能用最少的磁盘 I/O 完成定位与范围查询。

一、先排除其它结构

结构等值查询范围查询磁盘友好度为什么不适合做主索引
哈希表O(1)不支持一般只能等值命中,无法排序与范围扫描
二叉搜索树O(logN)支持数据量大时树高陡增,I/O 次数多
红黑树O(logN)支持千万级数据树高约 20+,读盘太多
B 树O(logN)一般较好非叶子也存数据,单页能容纳的 key 少
B+TreeO(logN)优秀最好—— 最终选择

二、B+Tree 胜出的四个点

  • 矮:非叶子节点只存索引 key 与指针,一个 16KB 页可存上千 key,三层即可支撑千万级数据。
  • 有序:叶子节点按 key 升序排列并用双向链表相连,范围查询、排序、分组都走顺序扫描。
  • 稳定:所有查询都要走到叶子层,路径等长,单条 SQL 耗时波动小,便于预估。
  • 冗余:key 全部冗余在叶子,非叶子只是路标,配合聚簇索引还能减少回表。
  • 预读友好:页内 key 连续存放,磁盘按页预读,顺序扫描吞吐更高。

三、InnoDB 中两类 B+Tree

聚簇索引(主键)  叶子节点 = 完整行记录,一张表只有一个
二级索引(普通)  叶子节点 = 索引列 + 主键值,可建多个

四、与磁盘 I/O 的关系

一次页读取 ≈ 一次磁盘 I/O
层数 = 定位一条记录必须的磁盘 I/O 次数
3 层 B+Tree ≈ 3 次 I/O 即可找到叶子页

常见追问与记忆点

  • 追问:为什么不用跳表?跳表更适合内存场景(如 Redis),磁盘场景更看重页预读与顺序 I/O。
  • 追问:页大小能改吗?能(innodb_page_size),改小树会变高,生产环境默认 16KB。
  • 记忆点:B+Tree = 矮 + 胖 + 叶子有序链表,用少量冗余换更少磁盘 I/O 与更好的范围扫描。
笔记加载中…