Skip to content

MySQL索引为什么使用b+树?

MySQL 索引使用 B+ 树,因为它在磁盘存储环境下能高效支持 范围查询顺序访问高扇出(Fan-Out),减少 I/O 操作,提升查询性能。相比其他数据结构(如 B 树、红黑树),B+ 树更适合数据库的索引需求,尤其在 InnoDB 引擎中。

关键事实

  1. B+ 树特点
    • 非叶子节点只存键值,不存数据,节省空间。
    • 叶子节点存所有数据,并通过链表连接,支持顺序遍历。
    • 高度低,扇出高(每节点可存更多键)。
  2. 为何适合 MySQL
    • 磁盘 I/O 优化:B+ 树高度低,一次磁盘读取加载更多键。
    • 范围查询高效:叶子节点链表顺序访问,快于跳跃式查找。
    • 查询稳定性:所有查询走叶子节点,路径长度一致。
  3. InnoDB 使用场景
    • 主键索引(聚簇索引):键是主键,数据是整行。
    • 二级索引:键是索引列,数据是主键值。

具体原因详解

1. 磁盘 I/O 效率

  • 背景:数据库索引存储在磁盘,I/O 是性能瓶颈。
  • B+ 树优势
    • 非叶子节点只存键,占用空间小,一个节点可存数百到上千个键(扇出高)。
    • 树高度低(如 3 层可存百万记录),减少磁盘读取次数。
  • 对比 B 树:B 树节点存键和数据,扇出较低,层数更高,I/O 更多。

2. 范围查询支持

  • 需求:SQL 常涉及 WHERE id BETWEEN 10 AND 20。
  • B+ 树优势
    • 叶子节点按键顺序排列,双向链表连接。
    • 找到范围起点后,顺序扫描即可,无需回溯。
  • 对比 B 树:数据分散在所有节点,范围查询需遍历多层。

3. 顺序访问性能

  • 背景:磁盘顺序读远快于随机读。
  • B+ 树优势
    • 叶子节点链表支持顺序扫描,充分利用预读(Locality)。
  • 对比红黑树:二叉结构,节点分散,随机访问多。

4. 查询稳定性

  • B+ 树优势
    • 所有数据在叶子节点,查询路径长度固定。
  • 对比 B 树:数据分布在各层,查询深度不一。

5. 空间利用率

  • B+ 树优势
    • 非叶子节点不存数据,更多空间存键,减少树高。
  • 示例:页大小 16KB,键 8 字节,可存约 2000 个键/节点。

示例

  • :id 主键,100 万行数据。
  • B+ 树
    • 高度 3 层,每节点 1000 个键。
    • 查询 id=500000:3 次 I/O(根 → 中间 → 叶子)。
  • 红黑树
    • 高度约 20 层,20 次 I/O。

延伸与面试角度

  • 为什么不用红黑树?
    • 二叉树高度高(O(log N),N 为 2),磁盘 I/O 多。
    • 无顺序链表,范围查询低效。
  • 为什么不用 B 树?
    • 数据分散,扇出低,范围查询需多层遍历。
  • 为什么不用哈希索引?
    • 哈希支持等值查询(O(1)),但不支持范围查询。
  • 实际应用
    • InnoDB 主键索引:B+ 树叶子存整行数据。
    • 二级索引:叶子存主键,需回表。
  • 性能数据
    • B+ 树查询百万数据,3-4 次 I/O;红黑树可能 20 次。
  • 面试点
    • 问“范围查询为何快”时,提叶子链表。
    • 问“与 B 树区别”时,提扇出和数据分布。

总结

MySQL 用 B+ 树因其高扇出减少 I/O、叶子链表支持范围查询和顺序访问,完美适配数据库的磁盘存储和查询需求。相比 B 树、红黑树,B+ 树在性能和功能上更优。面试时,可结合树高计算或范围查询示例,展示深入理解。