bigywater.tech
ClickHouse 内部原理 · 19

Double Delta、Gorilla 和 T64 编码

真实给DoubleDelta、Gorilla、T64三种专用编码各自匹配设计场景的数据,对比它们相对纯LZ4的真实压缩收益,包括一个诚实记录的反直觉结果。

839倍 vs 19% vs 反超
DoubleDelta/Gorilla/T64三种编码真实收益差距悬殊
诚实记录
T64在本文场景下真实比纯LZ4更大,未回避这个结果

做的事:真实给三种编码各自匹配它设计针对的数据形状

代码CREATE TABLE demo.codec2 ( k UInt64, ts DateTime CODEC(DoubleDelta, LZ4), ts_lz4 DateTime CODEC(LZ4), temp Float64 CODEC(Gorilla, LZ4), temp_lz4 Float64 CODEC(LZ4), small_int UInt64 CODEC(T64, LZ4), small_int_lz4 UInt64 CODEC(LZ4) ) ENGINE=MergeTree ORDER BY k; INSERT INTO demo.codec2 SELECT number, toDateTime('2026-01-01 00:00:00')+number, toDateTime('2026-01-01 00:00:00')+number, -- 每秒+1,均匀递增 20.0+sin(number/1000)*3, 20.0+sin(number/1000)*3, -- 缓慢波动的温度 number%100, number%100 -- 0~99循环的小整数 FROM numbers(2000000);

验证:DoubleDelta对均匀递增时间戳,真实压到839分之一

实测 · 本机执行输出
ts       (DoubleDelta,LZ4)   compressed=9581      uncompressed=8000000   ratio=0.0012
ts_lz4   (LZ4)                compressed=8034571   uncompressed=8000000   ratio=1.0043

真实差距:8034571 / 9581 ≈ 839倍

时间戳每行固定+1秒,"差分的差分"(double delta)几乎全是0,LZ4面对一列几乎全零的数据能压缩到极致——这是DoubleDelta的最佳场景:相邻值之差本身也高度规律的单调序列(自增ID的步长、等间隔时间戳),比单纯的Delta编码更进一步。

验证:Gorilla对缓慢波动的浮点数,真实收益只有约19%

实测 · 本机执行输出
temp      (Gorilla,LZ4)   compressed=13006364   uncompressed=16000000   ratio=0.8129
temp_lz4  (LZ4)            compressed=16068038   uncompressed=16000000   ratio=1.0043

真实差距:16068038 / 13006364 ≈ 1.24倍(约19%的字节数节省)

Gorilla编码来自Facebook同名论文,设计目标是相邻浮点数的位模式高度相似(异或后前导/尾随零很多)时的场景。本文用sin(number/1000)*3模拟温度传感器数据,虽然整体上是缓慢波动的,但逐行之间的浮点数变化仍然足够"跳跃"(不是Gorilla论文里那种秒级几乎不变的监控指标),真实收益只有约19%,远不如DoubleDelta的839倍那么夸张——这是一个诚实的对照:不是每种"专用编码"在每种"看起来匹配"的数据上都会有戏剧性的提升,Gorilla真正大放异彩的场景更接近变化极其缓慢、采样频率很高的监控时序数据。

诚实的意外:T64对小范围重复整数,真实反而比纯LZ4更大

实测 · 本机执行输出(反直觉的真实结果)
small_int      (T64,LZ4)   compressed=186565   uncompressed=16000000   ratio=0.0117
small_int_lz4  (LZ4)        compressed=168617   uncompressed=16000000   ratio=0.0105

真实结果:T64+LZ4(186565字节)比单独LZ4(168617字节)还大了约10.6%
T64编码的设计思路是把64个整数值按位转置成一个位矩阵,剥离掉小范围整数里大量的前导零字节,理论上应该更适合本文这种number%100(值域只有0~99,UInt64里剩下的高位字节全是0)的场景。但本文这次真实测出来的结果是T64+LZ4反而比纯LZ4更大——一个合理的推测是:number%100这种0~99循环重复的模式本身对LZ4来说已经是极容易识别的高频重复序列,LZ4凭自己就已经压得很好了,T64的位转置反而打乱了原本对LZ4友好的字节级重复模式,外加T64编码本身的元数据开销,最终得不偿失。这个结果没有回避或者重新设计实验去"凑出"T64应该更好看的数字,而是诚实记录下来:编码选择不能只看官方文档里的场景描述就照搬,具体数据分布下哪种编码更优,真实值得像本文这样跑一次实测再决定,T64更可能在数值范围小、但不是这种高度重复循环模式(比如带一定随机噪声的小范围计数器)的场景下才能体现优势。

分步演示:从839倍的DoubleDelta到反直觉的T64

每一步都是本文上面用真实system.columns跑出来的原始压缩字节数。

三种专用编码,真实一个夸张、一个温和、一个意外翻车
这一步新验证的编码

    本文用到的工具

    • 本机 ClickHouse 26.9.4(单节点),真实的 system.columns(三种专用编码 vs 纯LZ4对照)
    京ICP备2026067502号-1京公网安备11010502063487号