InnoDB的索引结构
答案
InnoDB 的索引结构采用 B+ 树,分为 聚簇索引(Clustered Index) 和 二级索引(Secondary Index)。聚簇索引以主键为基础,叶子节点存储整行数据;二级索引以索引列为键,叶子节点存储主键值,通过回表查询完整数据。所有索引都基于 B+ 树,优化磁盘 I/O 和范围查询。
关键事实
- 索引类型:
- 聚簇索引:主键索引,数据与索引一体。
- 二级索引:非主键索引,指向主键。
- B+ 树特点:
- 非叶子节点只存键值,节省空间。
- 叶子节点存数据,双向链表连接,支持顺序访问。
- 高度低,扇出高,减少 I/O。
- 存储方式:
- 聚簇索引:按主键顺序存储整行。
- 二级索引:按索引键排序,存主键。
具体结构详解
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+ 树或举查询示例,展示结构理解。