分类3.存储引擎 |篇章08 压缩编码适用版本TDengine v3.xv3.3.x / v3.4.x | 最后更新2026-06-02时序数据具有高度的规律性——时间戳单调递增、数值列缓慢变化、字符串列频繁重复。TDengine 利用这些特征设计了一阶类型特化编码 二阶通用压缩的双层压缩架构在不牺牲查询速度的前提下实现极高的压缩比。核心概念速查表概念说明COMP数据库压缩级别参数0/1/2一阶编码类型感知的轻量编码Delta、XOR等二阶压缩通用字节流压缩LZ4 / ZSTD / TSZDelta-of-Delta时间戳编码存储差值的差值XOR 差分浮点数编码只存储异或后的变化位Simple8B整数编码将多个小值打包到 64 位ZigZag有符号整数映射为无符号整数详细解析1. 双层压缩架构TDengine 压缩的两个层次 原始数据 │ ▼ ┌────────────────────────────────────────────┐ │ 一阶类型特化编码 │ │ │ │ 根据列的数据类型选择最佳编码算法 │ │ - TIMESTAMP → Delta-of-Delta │ │ - INT/BIGINT → ZigZag Simple8B │ │ - FLOAT/DOUBLE → XOR 差分 │ │ - BOOL → Bit Packing │ │ - BINARY/NCHAR → 字典编码 │ │ │ │ 特点轻量、解码快、利用数据特征 │ └────────────────────────────────────────────┘ │ ▼ ┌────────────────────────────────────────────┐ │ 二阶通用压缩COMP2 时启用 │ │ │ │ 对一阶编码后的字节流进行通用压缩 │ │ - LZ4高速压缩/解压压缩率中等 │ │ - ZSTD高压缩率解压稍慢 │ │ - TSZ浮点专用有损压缩可选 │ │ │ │ 特点进一步压缩残余冗余 │ └────────────────────────────────────────────┘ │ ▼ 磁盘存储2. COMP 参数COMP 值含义行为0不压缩原始数据直接写盘调试用1一阶压缩仅类型特化编码2默认双层压缩一阶编码 二阶通用压缩-- 创建数据库时指定压缩级别CREATEDATABASEpower COMP2;-- 修改压缩级别影响后续写入不影响已有数据ALTERDATABASEpower COMP1;3. 时间戳编码Delta-of-DeltaDelta-of-Delta 编码过程 原始时间戳等间隔采集 1 秒 [1000, 1001, 1002, 1003, 1004, 1005] Step 1: 计算一阶差值Delta [1000, 1, 1, 1, 1, 1] Step 2: 计算二阶差值Delta-of-Delta [1000, 1, 0, 0, 0, 0] 存储只需存第一个值 第一个 Delta 后续的 0 为什么有效 - 时序数据采集间隔通常固定1s / 5s / 1min - 二阶差值大多为 0 或非常小的数 - 0 和小值可以用极少位数表示Simple8B 打包 非等间隔情况 时间戳: [1000, 1001, 1003, 1004, 1006] Delta: [1000, 1, 2, 1, 2] D-of-D: [1000, 1, 1, -1, 1] → 虽然不全是 0但数值仍然很小4. 整数编码ZigZag Simple8BZigZag 编码处理有符号整数 问题-1 的补码表示需要 64 位全 1 ZigZag 映射有符号 → 无符号 0 → 0 -1 → 1 1 → 2 -2 → 3 2 → 4 ... 效果小绝对值映射为小无符号数 Simple8B 编码紧凑打包 将多个小值打包到一个 64-bit 整数中 ┌─────────────────────────────────────────────────────────┐ │ 64-bit word │ │ │ │ [4-bit selector] [60-bit payload] │ │ │ │ selector 决定 payload 的解读方式 │ │ selector1: 60 × 1-bit 值60个布尔值 │ │ selector2: 30 × 2-bit 值30个0~3的数 │ │ selector3: 20 × 3-bit 值 │ │ ... │ │ selector15: 4 × 15-bit 值 │ └─────────────────────────────────────────────────────────┘ 效果如果 Delta-of-Delta 都是 060 个值只占 8 字节5. 浮点数编码XOR 差分XOR 差分编码Gorilla 算法变体 原始浮点数[25.3, 25.4, 25.3, 25.5, 25.4] IEEE 754 二进制表示示意 25.3 → 0 10000011 10010100110... 25.4 → 0 10000011 10010110011... XOR 编码 第一个值: 完整存储 后续值: current XOR previous 25.3 XOR 25.4 0000...00010001...大部分位为 0 存储 XOR 结果 - 如果 XOR 0值未变→ 存 1 bit: 0 - 如果 XOR ≠ 0 → 存前导零数 有效位数 有效位 为什么有效 - 传感器数据通常缓慢变化温度 25.3 → 25.4 - 相邻值的 IEEE 754 表示大部分位相同 - XOR 后只有少量位不同 → 极少字节即可表示6. 布尔值编码Bit PackingBOOL 列编码 原始[true, false, true, true, false, true, true, true] Bit Packing ┌───┬───┬───┬───┬───┬───┬───┬───┐ │ 1 │ 0 │ 1 │ 1 │ 0 │ 1 │ 1 │ 1 │ 1 字节 └───┴───┴───┴───┴───┴───┴───┴───┘ 8 个 BOOL 值 → 1 字节压缩率 8:17. 字符串编码BINARY/NCHAR 列编码策略 策略一字典编码低基数 原始值[OK, ERROR, OK, OK, ERROR, OK] 字典{0: OK, 1: ERROR} 编码后[0, 0, 0, 0, 1, 0] → 每个值仅 1~2 字节 适用状态码、枚举值、设备型号等重复度高的列 策略二前缀压缩 LZ4高基数 原始值[sensor_001_temp, sensor_001_humi, ...] → 直接使用 LZ4/ZSTD 压缩利用公共前缀 适用设备 ID、日志文本等8. NULL 值处理NULL Bitmap 编码 每列有一个位图标记 NULL 位置 ┌───┬───┬───┬───┬───┬───┬───┬───┐ │ 0 │ 0 │ 1 │ 0 │ 0 │ 1 │ 0 │ 0 │ NULL 位图 └───┴───┴───┴───┴───┴───┴───┴───┘ V V N V V N V V V有效值NNULL NULL 值的列中 - Values 数组只存非 NULL 值? 不是—— - TDengine 为 NULL 位置仍保留占位空间简化随机访问 - 但连续 NULL 区域在二阶压缩时会被高效压缩 全 NULL 优化 - 如果整列全是 NULL → flag 标记 HAS_NONE - 不存储 Values 数组0 字节9. 压缩率参考数据类型场景典型压缩率COMP2TIMESTAMP等间隔采集20:1 ~ 50:1INT缓慢变化如转速5:1 ~ 15:1FLOAT传感器数据3:1 ~ 8:1BOOL开关状态8:1 ~ 16:1BINARY低基数枚举10:1 ~ 30:1BINARY高基数文本2:1 ~ 4:1综合压缩率典型 IoT 场景整体压缩率在6:1 ~ 20:1之间。代码示例观察压缩效果-- 查看超级表磁盘占用及压缩率showtabledistributedpower.meters\G;配置压缩参数-- 高压缩率配置存储优先CREATEDATABASEarchive COMP2;-- 低延迟配置性能优先CREATEDATABASErealtime COMP1;-- 不压缩调试/对比用CREATEDATABASEdebug_db COMP0;性能考量压缩与查询延迟的权衡COMP写入速度磁盘占用查询解码开销0最快无压缩最大无1快轻量编码中等低2中双层压缩最小中为什么 COMP2 查询不一定慢压缩的隐藏收益 无压缩COMP0查询一个块 磁盘读取 400KB → 耗时 4ms假设 100MB/s 解压0ms 总计4ms COMP2 查询一个块 磁盘读取 50KB → 耗时 0.5ms LZ4 解压 50KB → 耗时 0.1ms 一阶解码 → 耗时 0.1ms 总计0.7ms ← 反而更快 原因磁盘 I/O 通常是瓶颈 压缩减少 I/O 量 增加的 CPU 解码时间 → 对 I/O 受限的查询压缩反而加速编码选择对 CPU 的影响编码算法编码速度解码速度说明Delta-of-Delta~2 GB/s~3 GB/s极轻量Simple8B~1.5 GB/s~2.5 GB/s位操作为主XOR 差分~1 GB/s~2 GB/s位操作分支LZ4~400 MB/s~2 GB/s解码远快于编码ZSTD~100 MB/s~800 MB/s高压缩但编解码慢FAQQ1: 能否为不同列指定不同的压缩算法TDengine v3.x 中压缩算法由系统根据列类型自动选择用户不能逐列指定编码方式。COMP 参数是数据库级别的开关。Q2: COMP2 写入是否明显变慢通常不明显。一阶编码开销极低位操作二阶压缩LZ4也设计为高速。在 CPU 充足的环境下压缩减少的磁盘写入量可能反而提升写入吞吐。Q3: 修改 COMP 后旧数据会重新压缩吗不会。COMP 参数只影响后续写入的新数据块。已存储的数据块保持原压缩格式。如需统一压缩格式可以执行 COMPACT DATABASE 触发重写。Q4: TSZ 有损压缩是什么TSZ 是针对浮点数的有损压缩算法企业版可选允许在指定精度范围内丢失最低有效位换取更高的压缩率。适用于对精度要求不高的监控数据如温度精确到 0.1°C 即可。参考系统构架篇01-《TDengine 整体架构全景》02-《集群拓扑深度解析》03-《MNode 内部机制深度解析》04-《RPC 通信层深度解析》05-《VNode 生命周期》06-《RAFT 共识协议》07-《端到端的消息流》数据模型01-《数据库创建与参数详解》02-《超级表/子表/普通表》03-《支持数据类型深度解析》04-《TDengine Tag 设计哲学与 Schema 变更机制》05-《TDengine 虚拟表实现原理》存储引擎01-《TDengine 存储引擎概览》02-《TDengine MemTable 深度解析》03-《TDengine WAL 预写日志机制》04-《TDengine 数据文件格式》05-《TDengine Commit 与 Flush 机制 》06-《TDengine Compaction 合并策略 》07-《TDengine 数据保留与 TTL》关于 TDengineTDengine 专为物联网IoT平台、工业大数据平台设计。其中TDengine TSDB 是一款高性能、分布式的时序数据库Time Series Database同时它还带有内建的缓存、流式计算、数据订阅等系统功能TDengine IDMP 是一款AI原生工业数据管理平台它通过树状层次结构建立数据目录对数据进行标准化、情景化并通过 AI 提供实时分析、可视化、事件管理与报警等功能。