土法炼钢 · 系统与基础设施

【列存引擎内核】压缩与编码

文章导航

分类入口
databasestorage
标签入口
#clickhouse#compression#lz4#zstd#delta#gorilla#encoding#lowcardinality#24-lts

目录

列存的高压缩率来自 同列同质数据——整数 ID 用 Delta、时间戳用 DoubleDelta、监控指标用 Gorilla(Pelkonen et al., VLDB 2015),字符串默认 LZ4/ZSTD。ClickHouse 在 DDL 用 CODEC() 声明 列级 编解码链;读路径逆序解压再进入向量化算子(第 4 篇)。

压缩比必须在本机同数据集上实测——本环境未安装 ClickHouse,正文不给未跑过的压缩倍数。


一、两层结构:专用编码 + 通用压缩

flowchart LR
  RAW[原始列向量] --> SPEC[专用编码 Delta/Gorilla/...]
  SPEC --> GEN[通用压缩 LZ4/ZSTD]
  GEN --> BIN[.bin 压缩块]
例子 目的
专用编码 Delta, Gorilla, T64 利用数据模式降熵
通用压缩 LZ4, ZSTD 字节级压缩

DDL:ts DateTime CODEC(DoubleDelta, LZ4) — 先 DoubleDelta,再 LZ4。


二、LZ4 与 ZSTD

算法 解压 CPU 压缩率 场景
LZ4 热数据、低延迟
ZSTD 较高 冷归档、带宽受限

默认列压缩由 compression 表 setting 或 config.xml 默认 codec 决定;列级 CODEC 覆盖。

storage 压缩 通用原理一致:无免费午餐,高率必付 CPU。


三、Delta / DoubleDelta

适合单调或平滑序列(时间戳、自增 ID)。存差分后数值更小、重复模式更多,再 LZ4/ZSTD 效果更好。

CREATE TABLE ts (
  t DateTime CODEC(DoubleDelta, ZSTD),
  id UInt64 CODEC(Delta, LZ4)
) ENGINE = MergeTree() ORDER BY t;

不适合:高随机 UUID、已 hash 的均匀分布列——差分无规律,专用编码可能增大体积(工程判断,需本机验证)。


四、Gorilla 浮点编码

参考 Facebook Gorilla TSDB 论文;相邻浮点 XOR 后 leading/trailing zero 多,存 bit 长度与有效 payload。

可观测性 metrics 写入 ClickHouse 时常用(见 TSDB 内核 相关讨论)。

CREATE TABLE metrics (
  ts DateTime CODEC(DoubleDelta, LZ4),
  val Float64 CODEC(Gorilla, LZ4)
) ENGINE = MergeTree() ORDER BY ts;

五、T64、FPC 与其它整型编码

官方 Compression codecs 列出 T64(bit-packing)、FPC 等;可用性依赖类型与版本。选型以 system.codec_usage(若启用)与实测为准。


六、LowCardinality

低基数 String/Enum 转 字典 + 索引;存储与 group by 可受益。过高基数字典膨胀,反而更差。

CREATE TABLE logs (
  service LowCardinality(String),
  msg String CODEC(ZSTD)
) ENGINE = MergeTree() ORDER BY (service, ts);

七、与 PostgreSQL TOAST 对照

维度 ClickHouse CODEC PG TOAST
粒度 整列所有 granule 单行大字段
目标 扫描带宽 行大小上限
时机 insert/merge insert 超阈值
配置 DDL 显式 存储参数/autovacuum

PG 页面与 TOAST 对 OLTP 透明;ClickHouse 编码是 schema 设计决策


八、Benchmark 方法(实验台账)

本机 ClickHouse 24.x 对比同表不同 CODEC 应记录:

SELECT
  column,
  compression_codec,
  sum(data_compressed_bytes) AS compressed,
  sum(data_uncompressed_bytes) AS uncompressed
FROM system.columns
WHERE database = currentDatabase() AND table = 'bench_codec'
GROUP BY column, compression_codec
ORDER BY column;

未在本环境执行——正文不填压缩比数字。

可选:对同一查询比较 read_time / ProfileEventsCompressedReadBuffer*OSIOWaitMicroseconds(需本机 EXPLAIN PIPELINE / query_log)。


九、选型建议(工程判断,非 benchmark)

数据特征 建议 CODEC
时间戳 DoubleDelta + LZ4/ZSTD
缓慢变化 gauge Gorilla + LZ4
枚举/服务名 LowCardinality + ZSTD
随机 UUID 字符串 often 仅 ZSTD
已压缩 JSON NONE 或 ZSTD,避免无效 Delta

十、读路径解压成本

Scan 列时必须解压 所有选中 granule 覆盖的压缩块;高压缩率 + ZSTD 可能 CPU-bound。物化视图预聚合可换空间换时间(第 10 篇规划)。

flowchart TB
  MRK[Mark 定位块] --> READ[读压缩块]
  READ --> ZSTD[ZSTD 解压]
  ZSTD --> GOR[Gorilla 解码]
  GOR --> VEC[ColumnVector]

十一、merge 与压缩

Background merge 重写 Part 时可 重新选择 codec(若 ALTER MODIFY CODEC);merge 是压缩策略变更的落地时机(第 6 篇)。


十二、边界


十三、学术谱系:轻量编码 · Gorilla · 解压账单

阶段 文献 / 技术 本篇落点
经典 RLE / 字典 / Delta 族 CODEC 链前半段;LowCardinality
2015 Pelkonen et al., Gorilla, VLDB 浮点 XOR;监控指标列
列存系统 Abadi 等综述中的压缩清单 「同质列 → 高压缩」前提(第 01 篇三角)
工程 LZ4 vs ZSTD 通用层 率与 CPU 显式权衡

争论:追求最大压缩率(ZSTD 高档、重编码)vs 追求扫描吞吐(LZ4、轻 Delta)。论文常报压缩比;生产还要付 解压 CPU(第十节)与 merge 重写成本(第十一节)。

13.1 工程间隙

论文设定 ClickHouse 24.x
一次性 bulk load 后只读 持续 ingest + merge 反复编解码
单列理想分布 真实列混合高基数 UUID 与低基数枚举
内存常驻解压缓冲 云盘 + 有限 cache,解压可成瓶颈

13.2 开放问题

  1. 云盘场景下「压缩率拐点」在哪? 可检验:同列 LZ4 vs ZSTD 的端到端 scan CPU 与对象存储 GET 次数(入口:Gorilla VLDB’15;CH Compression)。
  2. LowCardinality 字典爆炸如何自动降级? 运维可见,算法侧仍开放。

上一篇Part 格式

下一篇向量化执行


参考资料

核心论文

  1. Pelkonen et al., Gorilla: A Fast, Scalable, In-Memory Time Series Database, VLDB 2015(A 级)。
  2. Abadi et al., Column-Stores vs. Row-Stores, SIGMOD 2008(压缩为列存栈一环;A 级)。

规范 / 源码 / 文档

  1. ClickHouse Documentation, Compression codecs(A 级)。
  2. ClickHouse Source, v24.3, src/Compression/src/DataTypes/Serializations/(A 级)。

编解码器链顺序

DDL 示例:value Float64 CODEC(Gorilla, ZSTD) 表示 先 Gorilla 专用编码,再 ZSTD 通用压缩。读路径逆序解压。

内置通用压缩:NONELZ4ZSTD(及 level 变体)。专用编码见官方 Compression codecs 表。

Delta 族数学

对序列 \(x_1,\ldots,x_n\),Delta 存 \(d_i = x_i - x_{i-1}\)(首元素规则见实现)。DoubleDelta 对 \(d_i\) 再差分,适合时间戳等二阶平滑序列。

Gorilla 参考

Pelkonen et al., Gorilla: A Fast, Scalable, In-Memory Time Series Database, VLDB 2015。XOR 压缩相邻浮点值的 leading/trailing zero 相同前缀。

LowCardinality

内部维护字典 + 索引列;对低基数 String/Enum 减少存储与 group by 字典优化。与 Plain 编码选择属于 DDL 设计(非自动 TOAST)。

读完这篇,下一步读什么

优先读同系列或同问题的下一篇,把单篇消费变成主题集群。

2026-06-18 · database / storage

【列存引擎内核】列存基础与 ClickHouse 架构

行存 vs 列存的带宽、压缩与向量化三角;ClickHouse Server 进程模型、线程池与 MergeTree 引擎家族地图;src/Storages 与 src/Processors 源码入口。对照 PG 行存与 LSM 写优化路径,版本锚定 ClickHouse 24.x LTS。

2026-06-18 · database / storage

【列存引擎内核】MergeTree Part 文件格式

ClickHouse MergeTree Part 目录结构:columns.txt、checksums.txt、.bin、.mrk2、primary.idx 语义,Granule 与 Mark 的定位作用,Wide/Compact 布局与 MergeTreeDataPart 源码入口。版本锚定 24.x LTS。

2026-06-18 · database / storage

【列存引擎内核】向量化执行引擎

ClickHouse Block 列向量 batch、IProcessor Pipeline 与 filter/project/aggregate 向量实现;对照 PostgreSQL 火山模型 ExecProcNode。源码入口 src/Processors、src/Columns。24.x LTS。

2026-06-18 · database / storage

【列存引擎内核】查询读取路径

MergeTree SELECT 读路径:Mark Range 定位 Granule、PREWHERE 与 WHERE、Part 级并行与 max_threads。EXPLAIN indexes=1 解读方法。24.x LTS,无伪造 EXPLAIN 输出。


By .