B+树与LSM树存储引擎的适用场景深度对比

阿乐
阿乐 管理员 黑卡会员
发布于 2026-09-11 15:44 ·5 浏览 ·0 回复

在数据库社区,关于 B+ 树和 LSM 树的争论几乎从未停止。有人坚持 MySQL/InnoDB 的 B+ 树是 OLTP 的黄金标准,也有人认为 RocksDB 这类 LSM 引擎才是写密集型场景的答案。其实两者没有绝对优劣,只有是否匹配工作负载。本文尝试从原理到场景,做一次深度对比。

核心差异:原地更新 vs 追加写

B+ 树以页为单位组织数据,更新时找到对应页原地修改。页满则分裂,可能触发随机写。读路径稳定,根到叶子通常 3-4 层,范围扫描通过叶子链表高效完成。

LSM 树把写操作先写入内存 MemTable,写满后冻结并刷成不可变的 SSTable,后台通过 compaction 合并。所有写都是顺序追加,这是它高写吞吐的根源。代价是读可能要查 MemTable 和多个 SSTable,产生读放大;compaction 又带来写放大和空间放大。

写路径:LSM 的天然优势

写密集场景下,B+ 树的随机写会成为瓶颈。每次更新可能触发页分裂、脏页刷盘、redo log 等,写放大明显。而 LSM 的追加写充分利用磁盘顺序带宽,尤其在 HDD 和普通 SSD 上,写入吞吐远高于 B+ 树。像 Kafka、HBase、Cassandra、RocksDB 都因此选择 LSM。

但 LSM 的写放大不可忽视。compaction 会把数据反复读写,写放大可能达到 10 倍以上。如果写入速率长期超过 compaction 能力,就会产生写停顿,导致 P99 延迟抖动。这也是很多 LSM 系统需要限流和调优的原因。

读路径:B+ 树更稳,LSM 靠优化

B+ 树的读性能可预测,点查和范围查都较稳定。LSM 的点查需要从新到旧查多个层级,最坏情况要扫很多 SSTable。虽然 Bloom filter 可以过滤大部分不存在的 key,但范围查询仍然可能放大。现代 LSM 引擎通过分层 compaction、block cache、前缀索引等优化,读性能已经大幅提升,但在极端读多写少场景下,B+ 树仍有优势。

适用场景:按读写比和延迟要求划分

- B+ 树更适合:OLTP 核心交易、订单、用户账户、读多写少或读写均衡、强事务、点查与范围查询混合、P99 延迟敏感、数据更新频繁且要求实时可见。
- LSM 更适合:写密集型应用,如日志采集、时序数据、IoT 设备上报、消息存储、feed 流、推荐特征、大数据批写、写吞吐优先且能接受读延迟波动。

另外,删除和更新模式也很关键。B+ 树原地更新,空间复用及时;LSM 的删除是追加墓碑,空间回收依赖 compaction,大量删除可能导致空间放大。

硬件与运维视角

SSD 时代,B+ 树的随机读很快,但随机写仍有写放大和寿命问题。LSM 的顺序写对 SSD 更友好,但 compaction 会消耗大量 I/O 和 CPU。运维上,B+ 树引擎通常更成熟稳定,LSM 需要关注 compaction 策略、层级配置、写停顿。TiDB 的 TiKV 选择 LSM 是为了分布式扩展和写吞吐,而 MySQL 的 InnoDB 选择 B+ 树是为了事务和读性能,都是场景驱动的结果。

选型没有银弹

选型时建议问几个问题:读写比是多少?P99 延迟要求多高?数据量和增长趋势?更新删除是否频繁?是否需要强事务?硬件是 HDD 还是 NVMe?团队能否驾驭 compaction 调优?如果读多写少、事务强、延迟敏感,B+ 树通常更稳;如果写吞吐是瓶颈、能接受后台合并,LSM 更合适。WiredTiger 同时支持两种引擎,也说明它们各有阵地。

结语

B+ 树与 LSM 树不是替代关系,而是不同权衡下的产物。B+ 树以读性能和稳定延迟见长,LSM 以写吞吐和顺序写取胜。理解读放大、写放大、空间放大的三角关系,结合真实工作负载做压测,比盲目站队更有意义。选型时,先看场景,再看引擎。

本文转载自 阿乐技术社区,原文地址:https://www.leleweb.cn/thread-225.html
转载请注明出处,版权归原作者所有。

全部回复 0

还没有回复,来抢沙发~