Apache TsFile 配置参数详解
基于 tsfile 2.4.0 实测解析 TSFileConfig 参数:页大小、ChunkGroup、编码器、压缩器、BloomFilter 默认值与配置入口,附 iotdb-system.properties 覆盖实测与生产配置模板。
Apache TsFile 配置参数详解
一、参数体系总览
TsFile 的运行期参数集中在 org.apache.tsfile.common.conf.TSFileConfig(对象)与 TSFileDescriptor(单例加载器)两个类中,配置入口有三层,优先级从高到低:
| 层级 | 入口 | 生效方式 | 实测说明 |
|---|---|---|---|
| 代码级 | TSFileDescriptor.getInstance().getConfig() 取到对象后调 setter | 当次进程立即生效 | 最直接,适合嵌入式写入程序 |
| 文件级 | classpath 下 iotdb-system.properties | 单例首次加载时读取 | 实测 2.4.0 的 TSFileConfig.CONFIG_FILE_NAME 常量值为 iotdb-system.properties(旧版的 tsfile-format.properties 不再是入口) |
| 默认值 | 类内字段初始化 | 未覆盖时兜底 | 2.4.0 共 20 个可调字段 |
另有一个程序化入口 TSFileDescriptor.getInstance().overwriteConfigByCustomSettings(java.util.Properties),可在代码里注入一组键值,语义与文件级相同。
获取默认值最可靠的方法是用反射逐字段打印。以下反射程序(可放入任意 tsfile 工程 main 中运行)实测于 tsfile 2.4.0:
TSFileConfig c = TSFileDescriptor.getInstance().getConfig();
String[] names = {"groupSizeInByte", "pageSizeInByte", "maxNumberOfPointsInPage",
"maxDegreeOfIndexNode", "maxStringLength", "floatPrecision", "rleBitWidth",
"deltaBlockSize", "plaMaxError", "sdtMaxError", "dftSatisfyRate",
"pageCheckSizeThreshold", "bloomFilterErrorRate", "batchSize",
"maxTsBlockSizeInBytes", "maxTsBlockLineNumber", "patternMatchingThreshold",
"lz4UseJni", "dfsHaAutomaticFailoverEnabled", "useKerberos"};
for (String n : names) {
java.lang.reflect.Field f = TSFileConfig.class.getDeclaredField(n);
f.setAccessible(true);
System.out.println(n + " = " + f.get(c));
}
实测回显(2.4.0 全量默认值,后文所有默认值均以此为准):
groupSizeInByte = 134217728
pageSizeInByte = 65536
maxNumberOfPointsInPage = 10000
maxDegreeOfIndexNode = 256
maxStringLength = 128
floatPrecision = 2
rleBitWidth = 8
deltaBlockSize = 128
plaMaxError = 100.0
sdtMaxError = 100.0
dftSatisfyRate = 0.1
pageCheckSizeThreshold = 100
bloomFilterErrorRate = 0.05
batchSize = 1000
maxTsBlockSizeInBytes = 131072
maxTsBlockLineNumber = 1000
patternMatchingThreshold = 1000000
lz4UseJni = true
dfsHaAutomaticFailoverEnabled = true
useKerberos = false
二、写入端核心参数解析
2.1 页与块结构参数
TsFile 落盘层级为 ChunkGroup → Chunk → Page,以下参数决定三级结构的切分粒度。
| 参数(字段名) | properties 键 | 默认值 | 说明 |
|---|---|---|---|
| groupSizeInByte | group_size_in_byte | 134217728(128 MB) | 单个 ChunkGroup 的字节阈值;一个设备的一组测点写满后整体落盘。嵌入式场景建议降到 8–16 MB,避免内存驻留过大 |
| pageSizeInByte | page_size_in_byte | 65536(64 KB) | 单个 Page 的字节阈值;Page 越小查询越灵活但元数据越多。实测本指南示例工程设为 64 KB 保持默认 |
| maxNumberOfPointsInPage | max_number_of_points_in_page | 10000 | 单个 Page 的点数上限,与 page_size_in_byte 双阈值先到先切 |
| pageCheckSizeThreshold | (2.4.0 未纳入文件键) | 100 | 写入时检查 Page 边界的扫描步长,一般不改 |
| maxStringLength | max_string_length | 128 | TEXT 值的最大长度(字节),超出写入报错。存长文本需调大 |
| batchSize | batch_size | 1000 | TSRecord/批量写入时的内部缓冲行数 |
设置示例(代码级,实测写入 4000 行成功):
TSFileConfig config = TSFileDescriptor.getInstance().getConfig();
config.setPageSizeInByte(64 * 1024); // 64 KB
config.setGroupSizeInByte(8 * 1024 * 1024); // 8 MB
2.2 编码器参数
各测点的编码器在 MeasurementSchema 构造时指定,TSFileConfig 中的编码类 setter 只决定"默认编码"(未在 schema 中显式指定时生效):
| setter | 对应 properties 键 | 默认行为 |
|---|---|---|
| setTimeEncoder / setValueEncoder | value_encoder(部分键由描述符读取) | 时间列与数值列默认编码 |
| setBooleanEncoding | — | BOOLEAN 默认 RLE |
| setInt32Encoding / setInt64Encoding | — | 整型默认 TS_2DIFF(二阶差分) |
| setFloatEncoding / setDoubleEncoding | — | 浮点默认 GORILLA |
| setTextEncoding | — | 文本默认 PLAIN |
| setRleBitWidth | — | RLE 位宽 8 |
| setDeltaBlockSize | — | 差分编码块大小 128 |
| setPlaMaxError / setSdtMaxError | — | PLA/SDT 有损压缩最大误差,默认 100.0 |
| setDftSatisfyRate / setFreqType | — | DFT 编码参数,默认满足率 0.1 |
各数据类型支持的编码集合(实测自 TSEncoding.TYPE_SUPPORTED_ENCODINGS,2.4.0):
| 数据类型 | 支持的编码 |
|---|---|
| BOOLEAN | RLE, PLAIN |
| INT32 / INT64 | ZIGZAG, GORILLA, CHIMP, SPRINTZ, RLE, PLAIN, RLBE, TS_2DIFF |
| FLOAT | GORILLA, CHIMP, SPRINTZ, RLE, PLAIN, RLBE, TS_2DIFF, GORILLA_V1 |
| DOUBLE | GORILLA, CHIMP, CAMEL, SPRINTZ, RLE, PLAIN, RLBE, TS_2DIFF, GORILLA_V1 |
| TEXT / STRING | PLAIN, DICTIONARY |
| TIMESTAMP / DATE | ZIGZAG, GORILLA, CHIMP, SPRINTZ, RLE, PLAIN, RLBE, TS_2DIFF |
| BLOB / OBJECT | PLAIN |
schema 级指定示例(实测 2.4.0 构造签名):
new MeasurementSchema("temperature", TSDataType.FLOAT,
TSEncoding.RLE, CompressionType.SNAPPY);
2.3 压缩器参数
压缩器枚举 CompressionType 实测包含 UNCOMPRESSED、SNAPPY、GZIP、LZ4、ZSTD、LZMA2 六种。
| setter | properties 键 | 说明 |
|---|---|---|
| —(schema 级指定为主) | compressor | 全局默认压缩器 |
| setBooleanCompression | boolean_compressor | 分类型压缩覆盖 |
| setInt32Compression / setInt64Compression | int32_compressor / int64_compressor | 整型覆盖 |
| setFloatCompression / setDoubleCompression | float_compressor / double_compressor | 浮点覆盖 |
| setTextCompression | text_compressor | 文本覆盖 |
| setLz4UseJni | lz4_use_jni | 默认 true,走 JNI 实现的 LZ4,性能更好;JNI 不可用时可关掉回退纯 Java |
注意:压缩依赖 zstd-jni、snappy-java、lz4-java、xz 四个库,Maven 引入 tsfile 时会自动传递,无需额外安装系统库。
2.4 索引与 BloomFilter 参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| maxDegreeOfIndexNode | 256 | 元数据索引树的分叉度,影响文件索引层高度与查询定位速度 |
| bloomFilterErrorRate | 0.05 | BloomFilter 误判率;越大文件越小但误判越多 |
| MIN_BLOOM_FILTER_ERROR_RATE | 0.01(常量) | 误判率下限(实测常量值) |
| MAX_BLOOM_FILTER_ERROR_RATE | 0.1(常量) | 误判率上限 |
| RLE_MAX_REPEATED_NUM | 32767(常量) | RLE 单次游程上限 |
| RLE_MAX_BIT_PACKED_NUM | 63(常量) | 位打包上限 |
说明:bloomFilterErrorRate 字段存在且默认 0.05,但在 2.4.0 的 TSFileDescriptor 字节码字符串中未见 bloom_filter_error_rate 属性键,即该字段暂不支持经 iotdb-system.properties 文件覆盖,需用 setter 调整(实测结论)。
2.5 查询与 TsBlock 参数
| 参数 | properties 键 | 默认值 | 说明 |
|---|---|---|---|
| maxTsBlockSizeInBytes | — | 131072(128 KB) | 查询结果 TsBlock 的字节上限 |
| maxTsBlockLineNumber | — | 1000 | TsBlock 行数上限,与上一条共同决定查询批大小 |
| patternMatchingThreshold | — | 1000000 | 正则/模式匹配算子的数据量阈值 |
2.6 存储与安全类参数
| 参数 | 默认值 | 说明 |
|---|---|---|
| dfsHaAutomaticFailoverEnabled | true | HDFS 多副本场景的主备自动切换开关(独立文件场景不涉及) |
| useKerberos | false | HDFS Kerberos 认证开关 |
| encrypt_type(properties 键) | — | 文件加密类型;配套 setEncryptKey / setEncryptSalt / setEncryptKeyFromToken |
| lz4_use_jni | true | 见 2.3 节 |
三、读端与工具行为参数
读端 API 本身不读取上述大部分写端参数,但以下几项直接影响读行为:
maxTsBlockSizeInBytes/maxTsBlockLineNumber(默认 128 KB / 1000 行):决定QueryDataSet每批返回的数据块大小,调小可降低查询内存占用,调大减少批次数。TsFileSequenceReader构造参数(实测签名):new TsFileSequenceReader(String path)最常用;另有带LongConsumer进度回调、带EncryptParameter解密、带两个 boolean(是否缓存元数据/是否只读 chunk 元数据)的重载。- 工具行为参数:
Tablet默认最大 1024 行(构造可指定),读端QueryExpression无参数数量上限,但路径需与写入时的对齐属性一致(new Path(device, measurement, true/false)第三参数表示是否对齐序列,实测不一致会查空)。
四、JVM 堆相关参数
TsFile 是嵌入式库,堆由宿主 JVM 决定。实测统一按 256–512 MB 限定:
| 场景 | 修改位置 | 示例 |
|---|---|---|
| Maven exec:java 运行 | 环境变量 MAVEN_OPTS(建议写入 ~/.bashrc) | export MAVEN_OPTS="-Xms256m -Xmx512m" |
| 打包后 java 直跑 | 命令行参数 | java -Xms256m -Xmx512m -cp 'target/app.jar:target/dependency/*' demo.Main |
| 部署脚本/守护进程 | JAVA_OPTS 透传 | 启动脚本中 eval java $JAVA_OPTS -cp ... |
实测验证一(ps 回显,Maven 3.9.16 / OpenJDK 17 环境):
root 1625 1 31 12:32 ? 00:00:04 /usr/lib/jvm/java-17-openjdk/bin/java --enable-native-access=ALL-UNNAMED -Xms256m -Xmx512m -classpath /opt/maven/boot/plexus-classworlds-2.11.0.jar ... org.codehaus.plexus.classworlds.launcher.Launcher -q exec:java -Dexec.mainClass=demo.HeapHolder
实测验证二(jps -v 回显):
1625 Launcher --enable-native-access=ALL-UNNAMED -Xms256m -Xmx512m -Dclassworlds.conf=/opt/maven/bin/m2.conf ...
实测验证三(程序内 Runtime.getRuntime().maxMemory()):
maxMemory=512MB
三处回显一致,说明堆上限 512 MB 已生效。写入侧与堆配合的两个关键点:groupSizeInByte 是单设备缓冲上限(默认 128 MB,256 MB 堆下建议 ≤ 64 MB);Tablet 容量默认 1024 行,实际内存约几百 KB 级,可放心分批。
五、配置生效实测
以"把页大小从 64 KB 调到 128 KB、浮点精度调为 3"为例,验证文件级配置生效。
(1)在工程 src/main/resources/iotdb-system.properties 写入(2.4.0 实测可识别的键):
page_size_in_byte=131072
compressor=SNAPPY
float_precision=3
(2)运行第一章的反射打印程序,实测回显:
pageSizeInByte = 131072
floatPrecision = 3
(3)结论:classpath 下的 iotdb-system.properties 在单例首次加载时生效,键名与字节码中提取的描述符键一致(实测可识别键包括:page_size_in_byte、group_size_in_byte、max_number_of_points_in_page、max_degree_of_index_node、max_string_length、float_precision、compressor、boolean_compressor、int32_compressor、int64_compressor、float_compressor、double_compressor、text_compressor、batch_size、lz4_use_jni、encrypt_type、user_encrypt_token 等)。
六、生产配置模板
以下为物联网边缘采集场景(单进程、中等吞吐、内存受限)的推荐组合,均来自实测参数:
import org.apache.tsfile.common.conf.TSFileConfig;
import org.apache.tsfile.common.conf.TSFileDescriptor;
public class TsFileProdConfig {
public static TSFileConfig build() {
TSFileConfig c = TSFileDescriptor.getInstance().getConfig();
// 分级落盘:控制单设备缓冲,适配 512MB 堆
c.setGroupSizeInByte(16 * 1024 * 1024); // 16 MB(默认 128MB)
c.setPageSizeInByte(32 * 1024); // 32 KB(默认 64KB)
c.setMaxNumberOfPointsInPage(8192); // 默认 10000
// 数值精度与文本
c.setFloatPrecision(3); // 默认 2
c.setMaxStringLength(1024); // 默认 128,按业务文本长度放大
// 压缩与索引
c.setLz4UseJni(true); // JNI 加速(默认 true)
// 查询批大小:读多写少场景适当调大
c.setMaxTsBlockSizeInBytes(256 * 1024); // 默认 128KB
return c;
}
}
对应 schema 级建议:整型遥测用 TS_2DIFF + ZSTD;浮点慢变序列用 GORILLA + SNAPPY;开关量用 RLE;标签文本用 DICTIONARY。实测同一 20000 点正弦 float 序列的组合体积对比(字节):
| encoder\compressor | UNCOMPRESSED | SNAPPY | GZIP | LZ4 | ZSTD |
|---|---|---|---|---|---|
| PLAIN | 84140 | 81504 | 70306 | 81826 | 69179 |
| RLE | 36728 | 34092 | 33508 | 34220 | 32960 |
| GORILLA | 74112 | 71476 | 64385 | 71759 | 63723 |
| TS_2DIFF | 26478 | 14386 | 10006 | 13996 | 8780 |
结论:正弦类光滑序列 TS_2DIFF+ZSTD 最省(较 PLAIN+UNCOMPRESSED 缩小约 10 倍);乱序无规律数据可退回 SNAPPY 保压缩速度。
七、常见问题
Q1:改了 TSFileConfig 的 setter 但没生效?
A:确认修改发生在首次创建 TsFileWriter 之前(单例加载后共享同一对象,setter 全局生效),且没有在 classpath 放置同名键的 iotdb-system.properties 把默认值顶回。
Q2:iotdb-system.properties 里写 bloom_filter_error_rate 为什么无效?
A:2.4.0 描述符未从文件读取该键(实测字节码键清单中不存在),只能通过 TSFileConfig 反射或 setter 设置。字段默认 0.05,合法区间 [0.01, 0.1]。
Q3:页大小与 ChunkGroup 应该谁大谁小?
A:必须满足 pageSizeInByte < groupSizeInByte(同设备同测点多个 Page 组成 Chunk,多个 Chunk 组成 ChunkGroup)。建议比例 1:256 至 1:512(如 32 KB : 16 MB),实测该比例下小文件场景元数据开销可忽略。
Q4:TEXT 字段写入报长度错误?
A:超过 maxStringLength(默认 128 字节)。调大 setter 或改用 BLOB 类型(仅 PLAIN 编码)。
Q5:256 MB 堆下写入 OOM?
A:优先把 groupSizeInByte 从 128 MB 降到 8–16 MB 并及时 flush();确认 Tablet 按批(≤1024 行)提交而非一次性构造超大批次。
八、参考链接
- TsFile 官网:https://tsfile.apache.org/
- TsFile GitHub 仓库(conf 包源码):https://github.com/apache/tsfile
- Maven Central:https://central.sonatype.com/artifact/org.apache.tsfile/tsfile
- IoTDB 官方文档(TsFile 格式与参数):https://iotdb.apache.org/zh/UserGuide/latest/Reference/File-Format-TsFile.html