首页/数据/NoSQL 速查/写路径差异:LSM 与 B 树
选型与架构50 条

写路径差异:LSM 与 B 树

存储引擎决定读写放大特征:LSM 类结构(写缓冲 + 不可变文件 + 后台合并)适合高吞吐写入,B 树原地更新适合点查与事务;很多系统是混合设计。

NoSQL 速查数据更新于 2026-10-13

两种写路径的本质差异

存储引擎决定系统的读写放大特征。B 树类引擎在原位置更新数据页并写预写日志,点查与范围扫描稳定,适合频繁更新与事务;LSM 类引擎把写入追加到内存表并周期性刷成不可变文件,后台再合并,写吞吐高但读取需要跨多个文件查找。理解这一点后,很多「调优」就变成了常识判断:攒批、避免小文件、给查询留可裁剪结构。

引擎对照

引擎写入路径读取特征代表系统
B 树原地更新页 + 预写日志点查稳定、范围扫描友好WiredTiger、InnoDB
LSM / 分段内存表追加写 + 后台合并不可变文件写吞吐高,读需跨多文件合并Lucene 段、ClickHouse part、RocksDB
混合内存结构 + 定期持久化读快,恢复与重建需要额外关注Redis 持久化、内存数据库

基本信息

写放大LSM 因反复重写文件而放大,B 树因页分裂与日志而放大
读放大LSM 需要查多个文件,常配布隆过滤器减少无效读取;B 树通常一次定位
空间放大LSM 在合并完成前会同时保留新旧数据
小批写入分段类引擎最怕高频小批:合并压力与碎片显著上升
删除语义B 树原地删除;LSM 常以标记删除并由后台合并清理

实践启示

  • 日志与事件流写多读少:分段类引擎更合适,注意攒批写入
  • 账户余额与状态类频繁更新:B 树加事务语义更稳
  • 避免高频单条写入分段引擎:按秒或按量攒批能显著降低合并压力
  • 理解删除与更新成本:分段引擎里删除是一次写入,不是原地抹除
  • 容量规划要算上合并期间的临时空间:空间使用会出现阶段性高峰
  • 选型看访问模式而非宣传指标:同一份数据在两种引擎上的表现可能相反

写法启示

写法启示
# 写入吞吐优先、可接受读放大:日志与事件流
# Lucene 段 / MergeTree part 追加写,批量提交优于逐条提交

# 点查与更新优先:账户余额、订单状态
# B 树 + 事务,单行更新不必重写整个文件

# 同一系统内可以分层:
# 明细分批落盘,热数据放内存表或缓存
把引擎模型当作选型的第一性判断:写多读少偏向追加写结构,更新密集且要求点查稳定偏向原地更新结构;实在分不清就用真实数据与真实读写比例做压测。
分段类引擎的空间占用会高于数据本身:合并未完成时新旧文件并存,容量按数据量估算容易出现「磁盘先满」的意外。

易错点

  • 用 LSM 类系统承载高频单行更新语义:更新被放大成写入,合并压力与空间放大随之而来
  • 小批量高频写入分段引擎:合并线程持续繁忙,查询延迟与磁盘占用同时恶化,攒批是首要优化
  • 按数据量等于磁盘占用来规划容量:忽略合并期间的临时空间与索引开销,容易出现容量告警
  • 把删除当作立即释放空间:分段引擎里的删除先标记、后由合并回收,容量下降有延迟

数据来源与参考

  • ClickHouse Docs: MergeTree
  • MongoDB Manual: WiredTiger storage engine
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌