面试场景还原
又是金三银四,会议室里的空气凝固。
面试官:我看你简历写精通各种中间件。那我问个基础的:MySQL 索引底层用什么?Redis 的 ZSet 底层用什么?HashMap 底层又用什么?
候选人:呃… MySQL 是 B+ 树,Redis ZSet 是跳表,HashMap 是红黑树?
面试官:没错。那为啥 Redis 不用 B+ 树?或者 MySQL 为啥不用跳表?它们选型的依据是什么?
候选人:这… 因为它们快?
面试官:回去等通知吧。
死记硬背八股文,遇到这种横向对比的场景题容易失分。今天带大家深入分析这些数据结构的选型逻辑。
MySQL 为什么使用 B+ 树
面试官:先说 MySQL,为啥 InnoDB 引擎非要用 B+ 树?用红黑树不行吗?
❌ 错误回答:因为 B+ 树更高级,名字带个加号。
✅ 正确回答:MySQL 的数据是存在磁盘上的,瓶颈在磁盘 IO。B+ 树就是为了减少磁盘 IO而生的。
把 B+ 树想象成一个超级扁平的多层书架:
- 矮胖结构:B+ 树一个节点能存很多索引,树的高度通常只有 3-4 层。这意味着查一条数据,最多读 3-4 次磁盘。
- 扫库神器:B+ 树的所有数据都挤在叶子节点,而且叶子节点之间有指针连着。你要查'ID 大于 100 的用户',找到 100 后顺着链表往后拉就行,支持范围查询非常高效。
如果是红黑树(二叉树),数据量一大,树高得吓人,读一次磁盘就像爬一层楼,效率低。
🔧 [实战场景]
这就是为啥千万别在 UUID 上建聚集索引,UUID 太长且无序,会让 B+ 树频繁分裂,影响性能。
-- 典型的 B+ 树应用场景:范围查询
-- 因为叶子节点有序且相连,这种 SQL 才能飞快执行
SELECT * FROM user WHERE age > 18 AND age < 30;
Redis ZSet 为什么选择跳表
面试官:既然 B+ 树这么强,Redis 的有序集合(ZSet)为啥不用?反而用个听起来很随意的'跳表'?
我:这就很有意思了。Redis 是内存数据库,它没那么在乎磁盘 IO 次数。
💡 [源码/原理]
ZSet 底层是用跳表(SkipList)+ 哈希表实现的。
- 跳表是什么? 就像给链表加了多级索引。你要查第 100 号元素,不用从头数,通过上层索引'跳'着找。
- 为啥不用红黑树?
- 范围查询:ZSet 常用来做排行榜(如 )。在跳表里找范围,找到起点直接往后遍历链表就行。在红黑树里找范围?你得中序遍历,逻辑复杂多了。


