极高 进阶
B+树索引原理#
一句话答案#
B+ 树非叶节点只存 key,叶子节点存数据且双向链表相连,3 层可存亿级数据,范围查询高效。
核心要点
InnoDB 还有:
1. 自适应哈希索引(Adaptive Hash Index,AHI)
- InnoDB 自动(非用户手动创建)为频繁访问的索引页建立哈希索引
- 当某个 B+ 树索引被频繁等值查询时,InnoDB 自动在内存中建立哈希索引,使等值查询 O(1)
- 完全由 InnoDB 自动维护,用户无法手动创建
- 可用
innodb_adaptive_hash_index开关控制
2. 全文索引(FULLTEXT)
- InnoDB 5.6+ 支持,基于倒排索引(与 ES 类似)
- 适合全文搜索,不适合普通 WHERE 条件
B+ 树 vs 哈希索引对比:
| 维度 | B+ 树 | 哈希索引 |
|---|---|---|
| 等值查询 | O(log N) | O(1),更快 |
| 范围查询 | ✅ 支持(叶子链表) | ❌ 不支持(哈希打散了顺序) |
| 排序 | ✅ 支持(叶子有序) | ❌ 不支持 |
| 前缀匹配 | ✅ 支持 | ❌ 不支持 |
| 哈希冲突 | 无此问题 | 有,冲突多时退化 |
| 存储 | 磁盘 + 内存 | 通常只在内存(Memory 引擎) |
什么时候用哈希索引:
- 确定只做等值查询(
=或IN),不需要范围、排序、前缀 - 使用 Memory 引擎的临时表
- InnoDB 的 AHI 会自动处理高频等值查询的优化,无需手动
面试回答(2分钟版)
InnoDB 索引采用 B+ 树结构。和 B 树的区别是:B+ 树非叶子节点只存 key 不存数据,所以每个节点能放更多 key,树更矮;叶子节点存完整数据并用双向链表相连,支持高效范围查询。一个 16KB 的页存 bigint 主键大约能放 1170 个指针,3 层 B+ 树就能索引两千万行数据,任何查询最多 3 次磁盘 IO。InnoDB 还有自适应哈希索引 AHI,对高频等值查询自动在内存建哈希索引做 O(1) 加速,不需要手动创建。为什么不用哈希索引做主索引?因为哈希打散了顺序,不支持范围查询、排序和前缀匹配,而 B+ 树的叶子链表天然有序都能支持。主键选自增 ID 而非 UUID 的原因也是为了顺序插入,避免随机写入导致频繁页分裂。
追问与易错
追问方向:
- “为什么不用哈希索引?”→ 哈希索引将 key 打散,不支持范围查询、排序和前缀匹配,只适合等值查询;B+ 树叶子链表天然有序,范围扫描和 ORDER BY 都能高效支持
- “一个 B+ 树节点能存多少 key?”→ InnoDB 默认页大小 16KB,bigint 主键 8 字节 + 指针 6 字节,一个非叶子节点可存约 1170 个 key,三层 B+ 树可索引约两千万行
- “主键用自增 ID 还是 UUID?为什么?”→ 自增 ID 顺序插入,新数据追加在 B+ 树尾部不会导致页分裂;UUID 无序随机写入频繁触发页分裂和页合并,写入性能差且索引空间膨胀
易错点:
- ❌ “B+ 树查找一定要走到叶子”——对的,但非聚簇索引找到主键后还要回表
- ❌ 混淆 B 树和 B+ 树——B 树非叶子也存数据