为什么用B+树而不是Hash索引?什么场景用Hash更好?
先说结论
B+树是默认选择,因为它同时支持等值查询、范围查询和排序。Hash索引只在纯等值查询场景更快,但MySQL InnoDB不支持手动创建(Memory引擎支持)。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
这道题几乎每场面试都会问。但如果你只说“B+树支持范围查询”就停了,面试官会觉得你只是背过。今天我用生产环境的实际场景来解释“什么时候用哪个”。
B+树为什么适合MySQL?
① 树高度低,磁盘IO少: B+树是多叉树(一般3-4层),1000万行数据只需要3-4次磁盘IO就能定位到数据。而二叉树可能需要20+次。
② 叶子节点有序链表: B+树的叶子节点通过双向链表连接,范围查询(WHERE price BETWEEN 10 AND 50)只需定位到起点,然后沿链表扫描就行。Hash索引做不到。
③ 支持排序: ORDER BY可以直接利用B+树的有序性,不需要额外排序。Hash索引是无序的。
Hash索引什么场景更好?
纯等值查询场景,Hash索引的时间复杂度是O(1),比B+树的O(log N)更快。比如:
• 缓存查询:Redis里的KV查询本质就是Hash
• MySQL Memory引擎的临时表
• InnoDB的自适应Hash索引(Adaptive Hash Index):InnoDB会自动对频繁访问的索引页建立Hash索引,加速等值查询
实战场景:为什么我们的表全用B+树
我在元宇宙社交App,所有的表都是InnoDB引擎,索引全是B+树。原因很简单:我们的查询场景90%以上都涉及范围查询或排序。比如“查询最近7天的动态”“按热度排序”“查询金额大于100的订单”——这些场景Hash索引都做不到。
面试加分:主动提到聚簇索引和非聚簇索引
聚簇索引(主键索引): 叶子节点存储的是完整的数据行。每张表只有一个聚簇索引。
非聚簇索引(二级索引): 叶子节点存储的是主键值。查到主键后还要回主键索引查完整数据,这就是回表。
如果二级索引已经包含了查询需要的所有字段,就不需要回表,这就是覆盖索引。这是上一篇“索引加了但还是慢”的解决方案。
总结
| 维度 | B+树索引 | Hash索引 |
|---|---|---|
| 等值查询 | O(log N),很快 | O(1),最快 |
| 范围查询 | 支持(叶子链表扫描) | 不支持 |
| 排序 | 支持(有序) | 不支持 |
| InnoDB支持 | 支持(默认) | 不支持手动创建 |
| 生产推荐 | 默认选择 | 纯等值场景才考虑 |
记住一句话:“有范围查询就用B+树,纯等值查询才考虑Hash”。能主动提到聚簇/非聚簇索引、回表、覆盖索引,说明你理解很深。
下一篇聊一个非常实用的场景:我有三个查询条件,组合索引怎么设计?顺序怎么定?
你们生产环境遇到过回表性能问题吗?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长