TDengine 列级压缩配置指南:ENCODE / COMPRESS / LEVEL 详解与原理分析
【免费下载链接】tdengineTDengine is an open source, high-performance, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, Industrial IoT and DevOps.项目地址: https://gitcode.com/taosdata/tdengine
TDengine 从 3.3.0.0 版本起提供了更高级的数据压缩特性,允许用户在创建表时为每一列单独配置是否压缩、采用哪种压缩算法以及压缩级别。本文以官方文档为核心,结合仓库源码与测试,系统讲解压缩的分级体系、各数据类型的默认算法、完整的 SQL 配置语法,以及压缩参数在底层源码中的校验与映射逻辑,帮助你在 IoT、IT 监控等场景下按数据特征精细调优存储开销与读写性能。
压缩术语:两级压缩与三级压缩档位
理解 TDengine 的列级压缩配置,首先需要厘清两个容易混淆的概念:压缩阶段(Compression Stages)与压缩级别(Compression Levels)。
压缩阶段(两级压缩)
- 第一级压缩(编码 Encoding):对数据进行编码,本质上就是一种压缩。例如整数的
simple8b编码、时间戳的delta-i差分编码、浮点数的delta-d/bss字节流拆分等,都属于第一级压缩。 - 第二级压缩:在编码结果之上,再对数据块执行一次通用压缩算法(如
lz4、zlib、zstd、xz、tsz),进一步压缩存储空间。
从源码结构看,TDengine 的压缩实现位于 source/util/src/tcompression.c,其中tsCompressINTImp、tsCompressDoubleImp、tsCompressBoolImp、tsCompressTimestampImp、tsCompressStringImp等函数分别实现了各数据类型的第一级编码;而l2CompressImpl_lz4、l2CompressImpl_zstd、l2CompressImpl_zlib、l2CompressImpl_xz、l2CompressImpl_tsz、l2CompressImpl_disabled则实现了第二级压缩(对应源码中的l2前缀,即 level-2,第二级压缩)。
压缩级别(三级档位)
文档中的"压缩级别"特指第二级压缩算法(如 zstd)的内部档位。以 zstd 为例,其原生支持至少 8 个级别,不同级别在压缩率、压缩速度和解压速度上各有取舍。为避免用户选择困难,TDengine 将其简化为以下三档:
high:压缩率最高,压缩与解压速度相对最差;low:压缩与解压速度最好,压缩率相对最低;medium:在压缩率、压缩速度、解压速度之间取得平衡。
算法清单与各数据类型默认配置
可用算法
- 第一级压缩(编码)算法:
simple8b、bit-packing、delta-i、delta-d、disabled、bss(byte-stream-split,字节流拆分) - 第二级压缩算法:
lz4、zlib、zstd、tsz、xz、disabled
其中tsz仅适用于FLOAT与DOUBLE类型。
各数据类型的算法与默认值
| 数据类型 | 可用编码算法 | 默认编码算法 | 可用压缩算法 | 默认压缩算法 | 默认压缩级别 |
|---|---|---|---|---|---|
INT/UINT | disabled/simple8b | simple8b | lz4/zlib/zstd/xz | lz4 | medium |
TINYINT/UTINYINT/SMALLINT/USMALLINT | disabled/simple8b | simple8b | lz4/zlib/zstd/xz | zlib | medium |
BIGINT/UBIGINT | disabled/simple8b/delta-i | simple8b | lz4/zlib/zstd/xz | lz4 | medium |
TIMESTAMP | disabled/delta-i | delta-i | lz4/zlib/zstd/xz | lz4 | medium |
FLOAT/DOUBLE | disabled/delta-d/bss | bss | lz4/zlib/zstd/xz/tsz | lz4 | medium |
BINARY/NCHAR | disabled | disabled | lz4/zlib/zstd/xz | zstd | medium |
BOOL | disabled/bit-packing | bit-packing | lz4/zlib/zstd/xz | zstd | medium |
DECIMAL | disabled | disabled | lz4/zlib/zstd/xz | zstd | medium |
源码中的默认值印证
上述默认值可以在 source/common/src/tcol.c 中找到对应实现。例如getDefaultEncode与getDefaultCompress函数根据数据类型返回默认编码与默认压缩算法:整型默认simple8b,时间戳默认delta-i,BINARY/NCHAR/DECIMAL默认zstd,TINYINT/UTINYINT/SMALLINT/USMALLINT默认zlib,其余多数类型默认lz4。getDefaultLevel则统一返回TSDB_COLVAL_LEVEL_MEDIUM,与文档中"默认压缩级别为 medium"一致。
编码与压缩算法的字符串常量定义在 include/common/tcol.h,例如TSDB_COLUMN_ENCODE_SIMPLE8B即"simple8b"、TSDB_COLUMN_ENCODE_BYTE_STREAM_SPLIT即"bss"、TSDB_COLUMN_COMPRESS_TSZ即"tsz"、TSDB_COLUMN_LEVEL_HIGH即"high",选项字符串缓冲区长度为TSDB_CL_COMPRESS_OPTION_LEN(12 字节)。
SQL 语法:创建表时指定压缩配置
建表(或建超级表)时指定压缩
CREATE TABLE [db_name.]tb_name ( col_name col_type [ENCODE 'encode_type'] [COMPRESS 'compress_type'] [LEVEL 'level'] [, ...] );tb_name:普通表或超级表的表名;encode_type:第一级压缩(编码)算法,取值见上文算法清单;compress_type:第二级压缩算法,取值见上文算法清单;level:第二级压缩级别,默认medium,也支持缩写'h'/'l'/'m'。
超级表(supertable)的列定义同样支持ENCODE、COMPRESS、LEVEL三个选项,具体语法可参考 创建超级表。
以下是一个完整的建表示例:
CREATE TABLE device_data ( ts TIMESTAMP ENCODE 'delta-i' COMPRESS 'lz4' LEVEL 'medium', device BINARY(64) COMPRESS 'zstd' LEVEL 'high', temp FLOAT ENCODE 'bss' COMPRESS 'tsz' LEVEL 'low', status BOOL ENCODE 'bit-packing' COMPRESS 'zstd', cnt INT ENCODE 'simple8b' COMPRESS 'zlib' );注意:ENCODE、COMPRESS、LEVEL均为可选子句,不指定时使用该列类型的默认配置。
修改已有列的压缩方式
ALTER TABLE [db_name.]tb_name MODIFY COLUMN col_name [ENCODE 'encode_type'] [COMPRESS 'compress_type'] [LEVEL 'level'];tb_name:表名,可以是超级表或普通表;col_name:要修改压缩设置的列,仅能为普通列(不能是标签 tag)。
例如:
ALTER TABLE device_data MODIFY COLUMN temp COMPRESS 'lz4' LEVEL 'medium';查看列的压缩方式
DESCRIBE [db_name.]tb_name;DESCRIBE会展示列的基本信息,包括列类型和压缩设置。从源码看,DESCRIBE 的结果列数量由DESCRIBE_RESULT_COLS_COMPRESS决定,且结果中专门包含名为compress的列(见 source/libs/parser/src/parTranslater.c 附近的实现),该列的值由 source/common/src/tcol.c 中的columnEncodeStr/columnCompressStr/columnLevelStr将内部数值转换为可读的字符串形式。
源码视角:压缩参数如何被校验与存储
SQL 解析与参数校验
压缩选项在 SQL 解析阶段被识别。在 source/libs/parser/src/parAstCreater.c 中,解析器通过strcasecmp(optionType, "ENCODE")等比较识别ENCODE/COMPRESS选项,并将非法参数映射为相应的错误码:编码非法报TSDB_CODE_TSC_ENCODE_PARAM_ERROR,压缩算法非法报TSDB_CODE_TSC_COMPRESS_PARAM_ERROR,压缩级别非法报TSDB_CODE_TSC_COMPRESS_LEVEL_ERROR。
参数合法性检查实现在 source/common/src/tcol.c:
checkColumnEncode:将用户输入的编码字符串转为小写后,与supportedEncode列表比对;checkColumnCompress:同理比对supportedCompress列表(共 6 项,见文件开头的supportedCompress[6]定义);checkColumnLevel:长度 1 时仅接受'h'/'m'/'l',否则比对supportedLevel列表;validColEncode/validColCompress/validColCompressLevel:进一步校验该算法是否适用于指定数据类型。
其中validColEncode中的注释清晰地总结了类型与编码的对应关系:
// |tinyint/smallint/int/bigint/utinyint/usmallinit/uint/ubiginint| simple8b | // | timestamp/bigint/ubigint | delta-i | // | bool | bit-packing | // | float/double | delta-d/byte-stream-split |而validColCompress中特别规定:tsz仅当列为FLOAT或DOUBLE时才合法,否则返回非法。
压缩选项的位域存储
校验通过后,编码、压缩算法、压缩级别被压缩进一个 32 位的整数:
setColEncode:编码值写入高 8 位(第 24-31 位);setColCompress:压缩算法值写入第 8-15 位;setColLevel:压缩级别写入低 8 位(第 0-7 位)。
若压缩算法为disabled,则压缩级别同时被置为TSDB_COLVAL_LEVEL_DISABLED。这一紧凑的位域设计使得每个列的压缩配置可以作为一个uint32_t随列元数据存储,具体可参考setColCompressByOption与createDefaultColCmprByType的实现。
压缩级别的底层映射
三档级别最终会映射为各算法内部的实际参数。在 source/util/src/tcompression.c 中可以看到一个映射表:
{"unknown", .lvl = {1, 2, 3}}, {"lz4", .lvl = {1, 2, 3}}, {"zlib", .lvl = {1, 6, 9}}, {"zstd", .lvl = {1, 11, 22}}, {"tsz", .lvl = {1, 2, 3}}, {"xz", .lvl = {1, 6, 9}},tsGetCompressL2Level根据L2_LVL_LOW/L2_LVL_MEDIUM/L2_LVL_HIGH三档分别取出对应算法的实际级别。例如:
zstd三档映射为 1 / 11 / 22,即low用级别 1、medium用级别 11、high用级别 22;zlib与xz映射为 1 / 6 / 9;lz4、tsz与unknown映射为 1 / 2 / 3。
这也解释了为什么high档"压缩率最高但速度相对最差":映射到的 zstd 22 级等参数会在压缩时显著提升压缩比,但付出更多 CPU 开销。
压缩执行路径
在数据落盘时,先执行第一级编码,再执行第二级压缩。以浮点列为例,tsCompressDouble(见 source/util/src/tcompression.c)会根据列元数据中的编码算法选择tsEncodeDouble等编码函数完成第一级编码,随后依据配置的第二级算法(lz4/zstd/zlib/xz/tsz)调用l2CompressImpl_*系列函数完成第二级压缩。解压时反向执行l2DecompressImpl_*与解码函数。l2CompressImpl_lz4使用LZ4_compress_default,l2CompressImpl_zstd使用ZSTD_compress(..., lvl)并将级别参数透传给底层算法。压缩与解压的完整往返逻辑可进一步参考仓库中的压缩测试用例 source/util/test/decompressTest.cpp。
兼容性说明
- 完全兼容已有数据:升级到 3.3.0.0 后,历史数据仍可正常读取与查询,压缩配置的新特性不影响已有数据文件;
- 不支持降级:升级到 3.3.0.0 之后无法回退到更低版本,规划升级时需注意。
实战建议
- 时间戳列:默认
delta-i+lz4已针对时序数据特征优化,通常无需修改;若对空间极度敏感,可尝试LEVEL 'high'提升压缩率。 - 浮点数列(温度、电压等传感器值):
bss编码对高位字节重复的浮点数据效果显著;若数据波动剧烈且希望极限压缩,可组合COMPRESS 'tsz'(tsz 为有损压缩,适用于对精度有容忍度的场景,需谨慎评估业务可接受误差)。 - 字符串列:默认
zstd压缩率优秀,长文本场景建议保持默认;BINARY/NCHAR不支持编码,只能配置第二级压缩。 - 布尔列:默认
bit-packing编码可将多个布尔值打包进更少的字节,适合大量开关类指标。 - 中小整型(
TINYINT/SMALLINT等):默认zlib,若追求写入/查询速度可改为lz4。
通过DESCRIBE可随时核对各列的最终压缩配置,便于在调优前后对比验证。
【免费下载链接】tdengineTDengine is an open source, high-performance, cloud native time-series database optimized for Internet of Things (IoT), Connected Cars, Industrial IoT and DevOps.项目地址: https://gitcode.com/taosdata/tdengine
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考