← 文章 / 数据与数据库
Simon Willison 13小时前 · 2026-08-10 08:37:21 · 2 阅读

SQLite 压缩文本历史原型实验

研究 SQLite 压缩文本历史原型 ——SQLite 压缩文本历史原型对比了 `WholeBlobHistoryStore`(每次编辑重写一个压缩的历史 blob)和 `ChunkedHistoryStore`(将压缩分块封存,以提升长历史的可扩展性)。两者都保留历史文本和时间戳,默认跳过未变更的替换,并通过 `BEGIN IMMEDIATE` 对写入操作加锁以保证原子性更新。

我对在关系型数据库里存储修改历史的方案一直很感兴趣。前几天遛狗时突然想到一个新点子:把所有历史版本的完整文本放进一个存字符串的大 JSON 数组里,再用 zlib 或 zstd 对整体压缩?由于字符串大量重复,压缩率肯定非常可观。

ChatGPT iPhone 应用新上线的GPT‑Live 语音模式效果相当不错,我就用它来讨论这个原型。目前还是无法分享语音对话的链接,不过下面是我从转写文本里摘出来的内容,原汁原味的意识流:

我有一个挺有意思的想法:对于一段在 SQLite 数据库某列里不断被编辑的文本,想办法以尽可能高效的方式保存它的所有历史版本。其实过去我也搭过类似的系统,但想找到真正高效的方案总是很难。最简单的做法就是:每改一次,就把旧值存成一行。但如果是个比较长的文档,比如 20KB 的大小,那就意味着每改一次,数据库里就多出 20KB 的数据。所以我就想,压缩应该会非常有效吧?如果你把这份文档从最初版本到当前版本的所有版本打包到一起,再用一种靠谱的压缩算法处理一遍,那基本上能干掉大量重复冗余的内容。所以我的思路是这样一个特别简单的机制:在同一张表上加一个历史列,用 BLOB 类型存二进制数据,里面塞一个用 Zlib 或者 ZSTD 压缩过的 JSON 文本数组,把所有旧版本都装进去。然后你大概还需要两列:一列就是这个神奇的 JSON 文本数组,另一列是一个 JSON 时间戳数组,这个根本不需要压缩,对吧?时间戳本质上就是个整数数组,Unix 时间戳。就这样,整个方案就完了。

然后我关掉了语音模式,给 GPT-5.6 Sol Pro 输入了下面这段文字提示:

用 Python 围绕这个思路搭建几个实验性原型

它吭哧吭哧跑了 38 分钟,最后给出了这个回答,以及你能在这个目录里看到的那些文件。

这个方案效果出奇地好!一份文档经过 1,000 次模拟修改后,原始修改文本加起来有 20.4 MB,但压缩成 Zstandard 压缩的 JSON 数组后只剩下 80.3 KB。

为了避免每次编辑都要解压再重新压缩整个数组的开销,Sol 建议把历史拆成多行,每行最多放 128 个版本,或者未压缩 JSON 体积不超过 3MB。

原始来源: Simon Willison

评论 (0)