← 返回题目列表

B+ 树和 LSM 树有什么区别?为什么写多场景常提 LSM?

高频 困难 第 14 / 25 题 更新于 2026/08/03
B+树LSM树存储引擎读写放大

简化版

B+ 树倾向于原地维护有序页,读和范围查询稳定,但随机写可能触发页分裂和随机 I/O。LSM 树把写入先追加到内存和顺序日志,再批量刷盘、后台 Compaction,写吞吐好,但读取可能查多层 SSTable,并带来读放大和写放大。

详细版

B+ 树和 LSM 都是存储引擎常见索引结构,但优化目标不同:

  • B+ 树:维护一棵页式有序树,点查和范围查路径短,更新直接作用于目标页;
  • LSM:写入先进入 MemTable 和 WAL,刷成不可变 SSTable,后台合并多层文件。

对比:

维度B+ 树LSM 树
写入可能随机改页追加写、批量刷盘
点查一棵树路径可能查 MemTable + 多层 SSTable
范围查叶子链表顺序扫多路归并多个文件
后台成本相对少Compaction 成本明显

写多场景常提 LSM,是因为它把随机写转成顺序写和批量合并,但并不是所有场景都比 B+ 树好。

完整版教学

一、两者解决的是同一个问题吗

B+ 树和 LSM 树都可以作为存储引擎的有序索引结构,用来支持按 key 查找和范围扫描。但它们面对磁盘的方式不同。B+ 树努力维护一棵随时有序、可直接查的页结构;LSM 树则接受数据分散在多个有序文件中,通过后台合并逐步整理。

所以它们不是简单谁淘汰谁,而是读写成本分配不同。B+ 树偏即时维护,LSM 偏延迟整理。

记忆钩子:B+ 树是边写边整理书架,LSM 是先把书放到收纳箱,晚上再批量归档。

二、B+ 树写入为什么可能贵

B+ 树插入要找到目标叶子页,然后把记录放进去。如果页满了,需要分裂页,并更新父节点。随机 key 会让写入分布在很多页上,导致随机 I/O、页分裂、缓存页频繁变脏。

例如随机插入 10000 条 UUID 主键,写入位置可能散落在大量叶子页;而自增主键大多写右侧末尾,局部性更好。B+ 树并不是不能写多,而是随机写模式会放大维护成本。

三、LSM 写入为什么吞吐高

LSM 写入通常先写 WAL 保证崩溃恢复,再写内存 MemTable。MemTable 满后刷成磁盘上的有序 SSTable 文件。这个过程主要是追加写和批量顺序写,避免每条写入都随机修改磁盘页。

write -> WAL append -> MemTable
MemTable full -> flush -> SSTable
background -> compaction -> larger SSTable

顺序写对磁盘和 SSD 都更友好,批量写还能摊薄排序和索引构建成本。

四、LSM 的读放大和写放大是什么

LSM 的代价来自多层文件。点查一个 key 时,可能要查 MemTable、Immutable MemTable、Level0 多个 SSTable,以及更低层文件。Bloom Filter 能减少无效查找,但不能完全消除复杂性。范围查询还可能需要多路归并多个有序文件。

写放大来自 Compaction:同一条数据可能在后台合并中被反复读写多次。删除也常通过 tombstone 标记,等 Compaction 才真正清理。

放大类型B+ 树LSM
读放大路径较稳定多层查找可能增加
写放大页分裂、日志、脏页Compaction 反复重写
空间放大碎片和页填充多版本和 tombstone

这三个放大是比较存储引擎时的高频词。

五、范围查询谁更强

B+ 树叶子页天然有序并通过链表连接,范围查询通常定位起点后顺序扫描。LSM 的每个 SSTable 内部有序,但同一范围的数据可能分布在多个层级和文件中,需要归并,还要处理新版本覆盖旧版本和 tombstone。

如果数据已经经过充分 Compaction,LSM 范围查询也可以不错;但在写入很猛、Level0 文件多时,范围查询压力会变大。B+ 树在传统关系型数据库的范围扫描和排序场景里非常稳定。

六、应该怎么选型

写多、吞吐优先、可接受后台 Compaction 抖动的场景,LSM 很有吸引力,例如日志型、时序型、KV 存储。读多、事务复杂、范围查询和低延迟稳定性要求高的场景,B+ 树仍然常见。

场景更常见选择
关系型 OLTP 索引B+ 树
写入吞吐很高的 KVLSM
强范围扫描和排序B+ 树常稳定
日志/时序追加写LSM 常合适

实际系统会结合缓存、Bloom Filter、压缩、事务模型和硬件特性,不是只看索引结构。

七、常见误区与追问

  • 误区:LSM 一定全面优于 B+ 树。 LSM 提升写吞吐,但会带来读放大、写放大和 Compaction 成本。
  • 追问:B+ 树为什么怕随机写? 随机写会修改分散页,触发页分裂和随机 I/O。
  • 误区:LSM 不需要排序。 MemTable 和 SSTable 都要保持有序,只是排序批量化和层级化。
  • 追问:Bloom Filter 在 LSM 中有什么用? 快速判断某个 SSTable 大概率不含 key,减少无效读。
  • 误区:B+ 树没有写放大。 日志、页分裂、脏页刷盘也会带来写放大,只是形式不同。

八、加强记忆

B+ 树和 LSM 的差别可以记成「即时维护 vs 延迟整理」。B+ 树每次写都努力维护页式有序结构,读路径稳定;LSM 先顺序写入,再后台 Compaction 整理,写吞吐强但读和后台成本更复杂。比较时一定带上读放大、写放大、空间放大,以及点查、范围查、写入吞吐这些维度。