Skip to content

InnoDB的索引结构

答案

InnoDB 的索引结构采用 B+ 树,分为 聚簇索引(Clustered Index)二级索引(Secondary Index)。聚簇索引以主键为基础,叶子节点存储整行数据;二级索引以索引列为键,叶子节点存储主键值,通过回表查询完整数据。所有索引都基于 B+ 树,优化磁盘 I/O 和范围查询。

关键事实

  1. 索引类型
    • 聚簇索引:主键索引,数据与索引一体。
    • 二级索引:非主键索引,指向主键。
  2. B+ 树特点
    • 非叶子节点只存键值,节省空间。
    • 叶子节点存数据,双向链表连接,支持顺序访问。
    • 高度低,扇出高,减少 I/O。
  3. 存储方式
    • 聚簇索引:按主键顺序存储整行。
    • 二级索引:按索引键排序,存主键。

具体结构详解

1. 聚簇索引(Clustered Index)

  • 定义
    • 主键索引,表数据按主键顺序存储。
    • 叶子节点包含完整行数据。
  • 结构根节点:键值范围(如 1, 10, 20) 中间节点:键值指针 叶子节点:主键 + 行数据(如 1: {id=1, name="Alice"})
  • 特点
    • 每张表只有一个聚簇索引。
    • 无显式主键时,InnoDB 自动生成隐藏列(如 6 字节 ROWID)。
  • 查询
    • SELECT * FROM table WHERE id = 5:直接定位叶子节点。

2. 二级索引(Secondary Index)

  • 定义
    • 非主键索引,如唯一索引、普通索引。
    • 叶子节点存储索引键和主键值。
  • 结构根节点:键值范围(如 name: A, M, Z) 中间节点:键值指针 叶子节点:索引键 + 主键(如 "Alice": 1)
  • 特点
    • 通过主键回表获取完整数据。
    • 支持覆盖索引(无需回表)。
  • 查询
    • SELECT name FROM table WHERE name = 'Alice':命中索引。
    • SELECT age FROM table WHERE name = 'Alice':回表查聚簇索引。

3. B+ 树实现

  • 节点
    • 页(Page):默认 16KB,存键和指针(非叶子)或数据(叶子)。
    • 扇出:一个节点可存数百到上千键(如 16KB / 8 字节 ≈ 2000)。
  • 高度
    • 百万数据约 3-4 层,I/O 次数少。
  • 链表
    • 叶子节点双向链接,支持范围查询(如 WHERE id BETWEEN 10 AND 20)。

示例

表结构

CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(50), age INT, INDEX idx_name (name) );

  • 聚簇索引:按 id 排序,叶子存 {id, name, age}。
  • 二级索引:按 name 排序,叶子存 {name, id}。

查询

  • SELECT * FROM users WHERE id = 5:
    • 直接查聚簇索引,O(log N)。
  • SELECT id FROM users WHERE name = 'Alice':
    • 先查 idx_name 找到 id=1,无需回表。
  • SELECT age FROM users WHERE name = 'Alice':
    • 查 idx_name 得 id=1,回表查聚簇索引。

延伸与面试角度

  • 为什么用 B+ 树?
    • 高扇出减少 I/O。
    • 叶子链表支持范围查询。
    • 对比 B 树:数据集中叶子,查询更高效。
  • 回表问题
    • 二级索引需额外查询聚簇索引,覆盖索引可优化。
  • 与其他引擎对比
    • MyISAM:非聚簇索引,叶子存数据指针,表分开存储。
    • InnoDB:聚簇索引数据即表,节省空间。
  • 实际应用
    • 主键查询快(如订单 ID)。
    • 范围查询(如时间段订单)。
  • 面试点
    • 问“回表如何优化”时,提覆盖索引。
    • 问“B+ 树优势”时,提扇出和链表。

总结

InnoDB 索引用 B+ 树,聚簇索引存完整数据,二级索引存主键值。B+ 树高扇出和叶子链表优化 I/O 和范围查询,适配数据库需求。面试时,可画简易 B+ 树或举查询示例,展示结构理解。