MySQL索引原理及底层数据结构

1 B+树索引数据结构

InnoDB索引底层采用**B+平衡树**,所有叶子节点到根高度一致,一般3‑4层;每个节点对应磁盘页,默认16KB

节点类型 存储内容
非叶子节点(根/分支) 只存**索引键 + 子节点指针**,不存真实行数据,方便更多索引加载进内存,减少磁盘IO
叶子节点 存储真实数据;叶子节点之间通过**双向链表相连,支持范围查询**

IO特点:树高3‑4层,查询最多3‑4次磁盘IO。

2 聚簇索引 & MyISAM非聚簇索引

  1. **InnoDB 聚簇索引(主键索引)**
  • 叶子节点直接存储**整行完整数据**,表数据本身就是B+树的叶子节点。
  • 一张表**只能有1个聚簇索引**:
  • 有主键:主键作为聚簇索引;
  • 无主键:选唯一非空索引;
  • 都没有:MySQL自动生成隐藏rowid作为聚簇索引。
  1. **InnoDB二级索引(普通索引、联合索引)**
  • 叶子节点存:**索引键 + 主键值**,**不存完整行数据**。
  • ⭐回表:查到主键后,再去聚簇索引B+树根据主键读取完整行,多一次B+树查找。
  1. **MyISAM(非聚簇)**
    主键、二级索引叶子都存**数据行的磁盘地址**,没有回表概念。
  2. **联合索引(复合索引)**
  • 多个字段组合构建索引,排序规则:先按第一个字段排序,第一个相同再按第二个字段排序。
  • 查询遵循**最左前缀匹配原则**。

3 B+树存储容量估算(面试常问)

磁盘页默认16KB,页头固定开销约120字节。

  1. 非叶子节点:每条索引键+指针约10B,单页可存:16\*1024 / 10 ≈ 1600个索引项
  2. 三层B+树:第一层根、第二层分支,可支持叶子节点总数 ≈ 1600 \* 1600 = 256万
  3. 叶子节点,单行100字节:单页存放约160行
  4. 理论总容量:256万 \* 160 ≈ 41亿行数据

    所以千万级表,3层B+树就足够。

4 B+树示意图

image

5 索引核心总结(背诵要点)

  1. B+树非叶子节点只存索引键和指针,不存行数据;叶子节点双向链表,高效支持范围查询。
  2. InnoDB聚簇索引叶子存放整行记录;二级索引叶子存放主键,需要回表拿完整数据。
  3. 联合索引遵守最左前缀匹配。
  4. 索引本质**空间换查询时间**;索引不是越多越好,索引会增加INSERT/UPDATE/DELETE写操作维护成本。

    高频面试题:
    Q:为什么InnoDB表必须要有主键?
    A:InnoDB是聚簇索引,数据存储依赖聚簇索引;没有主键MySQL会自动生成隐藏rowid,性能不如自定义主键,不推荐。
    Q:二级索引查询流程?
    A:走二级索引B+树找到主键 → 通过主键去聚簇索引B+树查询完整行(回表)。
    Q:B+树为什么适合数据库索引?
    1)树的高度很低,磁盘IO次数少;
    2)非叶子节点不存数据,可以缓存大量索引到内存;
    3)叶子双向链表,范围查询非常友好。