SQLite 文本修订历史的压缩存储实验

Simon Willison2026-08-11 05:03

问题:文本修订历史为何占空间

在关系型数据库中保存持续编辑文本的历史版本,最直接的做法是每次修改都存储一份完整文本。但对于约 20KB 的长文档,每次编辑都可能额外占用约 20KB,长期累积后存储成本较高。

实验方案:将完整历史整体压缩

该实验提出了一种较简单的实现方式:

  • 在 SQLite 表中使用 BLOB 字段保存历史内容;
  • 将每个历史版本的完整文本组成 JSON 字符串数组;
  • 对整个 JSON 数组使用 zlib 或 Zstandard 压缩;
  • 时间戳则单独保存为 Unix 时间戳数组,未必需要压缩。

其核心假设是:相邻修订版本通常存在大量重复文本,因此把所有版本放在一起压缩,能够利用跨版本重复内容获得较高压缩率。

实验结果

在一次包含 1000 次模拟修订的测试中:

  • 原始修订文本总量:20.4MB
  • Zstandard 压缩后的 JSON 历史数组:80.3KB

这说明,对于内容变化相对有限、版本之间重复度较高的文档,整体压缩完整历史可能显著减少存储体积。

实现上的取舍:避免每次编辑都重压全部历史

整体压缩也带来写入成本:每次新增修订都要解压现有历史、追加新版本,再重新压缩全部内容。

为减少这一开销,实验建议将历史拆分为多行分段保存。每个分段最多包含以下任一上限:

  • 128 个修订版本;
  • 3MB 未压缩 JSON 数据。

新增版本时通常只需处理最新分段,而不必反复解压和重压整个文档的完整历史。

适用场景与注意点

这种方案适合保留完整版本、且相邻版本高度相似的文本型数据,例如文档草稿、配置内容或持续编辑的记录。实际采用前仍需评估:

  • 读取单个历史版本时的解压和 JSON 解析成本;
  • 历史分段大小对读写延迟的影响;
  • 删除、检索和并发更新历史记录时的实现复杂度;
  • 文本变化幅度较大时,压缩率是否仍能保持优势。
评论

请登录后发表观点

暂无数据