
文章目录一、为什么通用压缩算法面对时序数据“力不从心”表 1 通用压缩与时序专属压缩对比二、差分压缩把完整时间戳变成差值三、增量压缩处理现实世界的采样抖动四、浮点压缩只保存发生变化的比特位五、时序数据库不是只选一种压缩而是组合压缩链路六、不同时序数据库的压缩设计取舍InfluxDB / Prometheus TSDB适合静态时序场景Apache IoTDB结合设备模型做分组压缩KaiwuDB在 LSM‑Tree 基础上兼顾动态时序TDengine压缩与自研分片模型深度绑定七、真正拉开差距的不只是算法本身八、总结上一篇我们聊了为什么绝大多数时序数据库都会选择 LSM‑Tree 作为底层存储引擎它依靠内存缓冲加顺序落盘扛住了物联网、车联网 7×24 小时海量数据写入解决了“写得进”的问题。但紧接着下一个现实难题就摆在面前存不下。传感器、电表、车载终端每秒源源不断输出测点比如温度、电压、振动、转速。百万级设备持续采集几个月原始时序数据就会迅速膨胀。如果原样存储磁盘成本和 IO 开销都会变得很高。gzip、Snappy 这类通用压缩算法大家并不陌生但它们并不是为时序数据设计的。时序数据要获得真正有效的压缩通常需要先识别出时间单调、数值连续、浮点高位相似等规律再做数学层面的预处理。今天这篇文章我们一次性把这些问题讲清楚拆解差分压缩、增量压缩、浮点压缩的核心逻辑对比通用压缩与时序专属压缩的差异并看看不同时序数据库在压缩能力上的设计取舍。一、为什么通用压缩算法面对时序数据“力不从心”通用压缩的核心思路是把数据当成字节流寻找重复字符串然后用字典或短编码替换重复片段。它很适合文本、日志、报文这类重复片段明显的数据。但时序测点数据有几个典型特征数据主体是时间戳、整型数值、浮点数值而字节层面的长重复串并不多连续采样的数值往往是平滑变化的而不是大块字符串重复时间戳本身单调递增但原始时间戳占用空间很大。因此通用压缩往往抓不住时序数据最关键的规律——时间连续和数值渐变只能在字节重复层面做压缩压缩比提升的空间会比较有限。真正高效的时序压缩是先通过数学变换去掉冗余再交给通用压缩做二次压缩。表 1 通用压缩与时序专属压缩对比对比维度通用压缩算法时序专属压缩压缩依据字节重复、字典替换时间单调、数值连续、浮点位相似处理对象任意二进制字节流时间戳、整型、浮点测点核心逻辑统计重复字节片段求差值、求增量、位裁剪处理层级直接压缩原始数据先预处理再二次压缩优势场景文本、日志、报文传感器、物联网、工业时序短板难以识别数值连续关系乱序、剧烈突变会降低收益 小结论 时序数据库并不是不用通用压缩而是通常会先做时序预处理再把结果交给 Snappy、ZSTD 这类通用压缩形成更高的整体压缩比。二、差分压缩把完整时间戳变成差值差分压缩主要针对时间戳和单调递增整型。一条原始时间戳可能占用 8 字节。如果百万条数据都存储完整时间戳空间开销会非常大。但时序场景中时间戳通常有一个重要特点按采集顺序向前推进前后差值很小。差分压缩的思想很简单不保存每个时间戳的完整值而是保存 “当前时间戳减去上一个时间戳” 的差值。设第 i 条时间戳为t_i则差分结果为d_i t_i - t_(i-1)实际存储时通常只需要保存一个基准时间戳再保存后续的差值序列。解码时用基准值依次累加差值就能还原全部时间戳。举例来说原始时间戳1000, 1100, 1200, 1300差分后基准 1000, 差值 100, 100, 100如果采样严格等间隔差值会大量重复后续再配合字典压缩压缩效果会非常明显。不过差分压缩也有边界。一旦出现乱序、补传或时间戳跳变差值会忽大忽小压缩收益就会下降。三、增量压缩处理现实世界的采样抖动理想情况下采样间隔固定差分后会得到大量相同差值。但现实中网络抖动、传感器休眠、系统调度都会让采样间隔出现轻微变化。这时可以在一阶差分的基础上再做一次差分也就是所谓的增量压缩或二阶差分。一阶差分d_i t_i - t_(i-1)二阶增量Δ_i d_i - d_(i-1)它的目标不是压缩原始时间戳而是压缩 “差值的变化”。举例来说原始时间戳1000, 1102, 1201, 1303一阶差分102, 99, 102二阶增量-3, 3可以看到虽然一阶差值并不完全相同但二阶增量的绝对值通常很小。在很多接近等间隔的场景中二阶增量甚至会大量等于 0从而可以用很少的比特存储。因此增量压缩比一阶差分更适合处理真实工业现场中 “近似等间隔但不完全均匀” 的数据。工程提示IoTDB、KaiwuDB、InfluxDB 等产品都在不同形式上支持二阶增量或类似的时间戳压缩逻辑差异主要体现在编码实现、比特打包和对乱序窗口的处理上。四、浮点压缩只保存发生变化的比特位差分和增量压缩解决的主要是时间戳的存储问题而浮点测点才是时序数据里最有压缩价值、也最有挑战的部分。温度、压力、电压这类数据经常在小范围内连续变化。例如25.134, 25.136, 25.135, 25.137如果把它们看作 IEEE 754 浮点数连续数值之间常常有大量高位比特完全相同。浮点压缩的核心就是只保存发生变化的低位比特。Gorilla 类浮点压缩的基本思路是将当前浮点数与上一个浮点数按位对比找出高位相同前缀和低位变化部分如果相同前缀很长就只编码变化部分如果数值突变导致差异很大则保存完整浮点数。例如上一个值1011 0101 0011 1010当前值1011 0101 0100 0011其中高位1011 0101完全相同真正变化的是后面一部分低位。浮点压缩可以只记录变化部分从而减少存储空间。这种方法对平滑变化的传感器数据特别有效。但如果测点频繁跳变新旧值差异很大压缩收益会明显回落。三类算法针对的数据形态不同适用场景也各有侧重放到一起对比会更直观算法核心原理适合对象最佳场景收益下降场景差分压缩一阶差值时间戳、单调整型严格等间隔、纯追加数据乱序、补传、历史修正增量压缩二阶差分时间戳、近似等间隔序列工业现场、轻微抖动采样时间戳大幅跳变浮点压缩位异或、位裁剪浮点测点滑变化的传感器数据频繁剧烈跳变五、时序数据库不是只选一种压缩而是组合压缩链路实际工程中时序数据库通常不会只使用单一压缩算法。更常见的链路是对时间戳做差分或二阶增量压缩对整型做差分压缩对浮点型做 Gorilla 类位裁剪压缩将预处理后的数据再交给 Snappy 或 ZSTD 做二次压缩最终写入底层存储文件。这个链路里前几步负责去除时序数据的数学冗余最后一步负责压缩字节层面的剩余重复。不同产品的主要差异在于当数据不再理想时还能不能保住压缩比。六、不同时序数据库的压缩设计取舍InfluxDB / Prometheus TSDB适合静态时序场景InfluxDB 和 Prometheus TSDB 都完整吸收了 Gorilla 压缩体系。在纯追加、很少历史改写的监控和简单物联网场景中压缩表现很好。但如果出现大量乱序补传或历史数据更新序列连续性会被破坏压缩比可能明显下降。InfluxDB 后续版本通过限制乱序窗口等方式做了一定缓解但本质上更适合相对规整的静态时序数据。Apache IoTDB结合设备模型做分组压缩IoTDB 的特点是把压缩和设备树形模型结合起来按设备、测点组织数据再做差分和二阶增量压缩。对于设备数量大、测点数量多、序列相对连续的工业物联网场景这种分组方式可以提升压缩收益。不过如果跨设备写入非常混乱或者历史修正很多序列连续性同样会受到影响压缩效率也会下降。KaiwuDB在 LSM‑Tree 基础上兼顾动态时序KaiwuDB 同样实现了差分、二阶增量和 Gorilla 浮点压缩体系。它的不同之处在于针对标准 LSM‑Tree 做了内核层面的适配增加了乱序写入窗口和更新标记机制。这使得它在面对车联网、能源行业常见的补传、历史修正等动态时序场景时不会因为少量乱序数据直接破坏整体压缩效率。此外KaiwuDB 还把压缩能力和冷热分层结合起来。热数据使用较轻的压缩策略保证查询性能冷数据使用更高压缩档位降低长期存储成本。TDengine压缩与自研分片模型深度绑定TDengine 没有采用标准 LSM‑Tree而是基于自研时序分片模型组织数据。它的压缩逻辑和分片强相关。分片内部数据有序时差分和浮点压缩都能发挥作用但如果乱序数据频繁进入特定分片分片内部有序性被破坏压缩收益也会受到影响。所以TDengine 的压缩表现高度依赖数据模型设计和分片策略是否贴合业务。七、真正拉开差距的不只是算法本身很多人会误以为时序数据库的压缩能力主要取决于是否实现了差分、增量或 Gorilla 算法。但实际上这些算法本身属于公开的时序压缩理论大多数主流产品都会支持。真正影响实际压缩比的往往是下面几个工程问题数据写入是否有序乱序补传窗口是否可控历史更新是否会破坏序列连续性存储引擎是否为动态时序做了专门适配压缩策略是否和冷热分层结合。换句话说算法决定压缩上限存储模型决定这个上限能不能在真实业务中落地。八、总结通用压缩主要按字节重复建立字典很难利用时序数据的时间连续和数值渐变规律差分压缩把完整时间戳压缩成差值适合单调递增序列增量压缩对差值再做差分适合处理轻微采样抖动浮点压缩通过位对比和位裁剪只保存浮点数中发生变化的部分主流时序数据库通常会组合使用时间戳压缩、测点压缩和通用压缩InfluxDB、Prometheus 更适合静态时序IoTDB 更适合设备模型清晰的工业采集TDengine 的压缩表现和分片设计关系很大KaiwuDB 则更强调在动态时序场景下保持压缩效率。