

90% 开发者不知道的 IoTDB 扩展技巧:UDF 从入门到落地全流程
本文聚焦 IoTDB 用户自定义函数(UDF)核心能力,详解 UDTF(时序生成函数)与 UDAF(聚合函数)的区别及适用场景。涵盖 UDF 注册、卸载、权限配置等管理操作,拆解从依赖配置到代码实现的完整开发流程,提供 5 个可直接复用的实战示例(含窗口计算、数据聚合等场景)。同时解答版本更新、内存优化等常见问题,帮助开发者快速掌握个性化时序数据处理能力,适配工业级场景需求。

1. UDF 介绍
UDF(User Defined Function,用户自定义函数)是 IoTDB 提供的灵活扩展能力——除了系统自带的时序处理函数,你还能通过自定义函数满足更多个性化计算需求。
IoTDB 支持两类核心 UDF,具体区别如下:
| UDF 分类 | 数据访问策略 | 描述 |
|---|---|---|
| UDTF | MAPPABLE_ROW_BY_ROW、ROW_BY_ROW、SLIDING_TIME_WINDOW、SLIDING_SIZE_WINDOW、SESSION_TIME_WINDOW、STATE_WINDOW | 自定义时间序列生成函数,输入 k 列 m 行数据,输出 1 列 n 行数据(m 和 n 可不同),仅能用于 SELECT 子句 |
| UDAF | - | 自定义聚合函数,输入 k 列 m 行数据,输出 1 列 1 行数据,可用于 SELECT、HAVING 等聚合函数支持的子句 |
1.1 UDF 使用
UDF 的用法和内置函数差不多,直接在 SQL 里调用就行,还支持多种灵活的查询场景:
-
基础 SQL 语法兼容:支持 SLIMIT/SOFFSET、LIMIT/OFFSET,也能做值过滤和时间过滤,和普通查询无缝衔接。
-
带 * 的批量查询:如果有 root.sg.d1.s1 和 root.sg.d1.s2 两个时间序列,这些查询方式都能用:
SELECT example(*) from root.sg.d1:会返回 example(s1) 和 example(s2) 两个结果;SELECT example(s1, *) from root.sg.d1:会生成 example(s1,s1) 和 example(s1,s2) 两个结果;SELECT example(*, *) from root.sg.d1:会包含 example(s1,s1)、example(s2,s1)、example(s1,s2)、example(s2,s2) 四个结果。
-
自定义键值对参数:查询时能给 UDF 传任意个键值对参数,键和值都要用单引号或双引号括起来,而且要放在时间序列后面。比如:
SELECT example(s1, 'key1'='value1', 'key2'='value2'), example(*, 'key3'='value3') FROM root.sg.d1;SELECT example(s1, s2, 'key1'='value1', 'key2'='value2') FROM root.sg.d1;
-
嵌套查询:可以和其他表达式、函数嵌套使用,比如:
SELECT s1, s2, example(s1, s2) FROM root.sg.d1;SELECT *, example(*) FROM root.sg.d1 DISABLE ALIGN;SELECT s1 * example(* / s1 + s2) FROM root.sg.d1;SELECT s1, s2, s1 + example(s1, s2), s1 - example(s1 + example(s1, s2) / s2) FROM root.sg.d1;
2. UDF 管理
2.1 UDF 注册
想使用自定义 UDF,得先完成注册,步骤很清晰:
- 先写好 UDF 类(比如全类名是 org.apache.iotdb.udf.UDTFExample);
- 把项目打成 JAR 包(用 Maven 管理的话,后面有示例可以参考);
- 按注册方式做准备,再执行注册 SQL:
CREATE FUNCTION <UDF名称> AS <UDF全类名> (USING URI URI地址)。
注册有两种方式,选一种就行:
- 方式一:手动放 JAR 包:先把 JAR 包放到集群所有节点的 ext/udf 目录(这个目录能配置),再执行
CREATE FUNCTION example AS 'org.apache.iotdb.udf.UDTFExample'; - 方式二:集群自动下载:先把 JAR 包传到 URI 服务器,确保 IoTDB 能访问到,再执行
CREATE FUNCTION example AS 'org.apache.iotdb.udf.UDTFExample' USING URI 'http://jar/example.jar',IoTDB 会自动下载并同步到整个集群。
这里有几个小提醒:
- 注册时不用启停服务器,IoTDB 会通过反射动态加载 UDF;
- UDF 名称不区分大小写,但不能和内置函数重名,否则会失败;
- 不同 JAR 包里别放全类名相同但功能不一样的 UDF 类,不然 SQL 里同时用的时候,系统可能随机加载,导致结果出错。
2.2 UDF 卸载
不想用某个 UDF 了,直接执行卸载 SQL 就行:DROP FUNCTION <UDF名称>。比如卸载上面注册的 example:DROP FUNCTION example。
2.3 查看所有注册的 UDF
想知道当前集群注册了哪些 UDF,执行 SHOW FUNCTIONS 就能看到完整列表。
2.4 UDF 配置
可以在 iotdb-system.properties 文件里调整 UDF 的相关配置:
- UDF 存储目录:
udf_lib_dir=ext/udf(默认是这个路径,可按需修改); - 内存相关配置(如果用 UDF 时提示内存不足,改这些参数后重启服务):
udf_initial_byte_array_length_for_memory_control=48:估算 UDF 查询中文本字段的内存占用,建议设得比所有文本的平均长度略大;udf_memory_budget_in_mb=30.0:单个 UDF 查询最多能用的内存(单位 MB),上限是读取分配内存的 20%;udf_reader_transformer_collector_memory_proportion=1:1:1:UDF 内存分配比例,格式是 a🅱️c(a、b、c 都是整数)。
2.5 UDF 用户权限
使用 UDF 得有 USE_UDF 权限,有了这个权限才能做注册、卸载和查询操作。具体的权限管理可以看专门的权限管理语句文档。
3. UDF 函数库
IoTDB 基于 UDF 能力,提供了一系列现成的时序数据处理函数,覆盖数据质量、数据画像、异常检测、频域分析、数据匹配、数据修复、序列发现、机器学习等场景,完全能满足工业领域的常用需求。
想使用这些函数,参考 UDF 函数库文档,按里面的安装步骤和注册语句操作,就能正确注册并使用了。
4. UDF 开发
4.1 UDF 依赖
如果用 Maven 开发,需要添加下面的依赖,注意版本要和目标 IoTDB 服务器一致:
<dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>udf-api</artifactId>
<version>1.0.0</version>
<scope>provided</scope>
</dependency>
4.2 UDTF(User Defined Timeseries Generating Function)
开发 UDTF 要继承 org.apache.iotdb.udf.api.UDTF 类,至少得实现 beforeStart 方法和一个 transform 方法。
接口说明
| 接口定义 | 描述 | 是否必须 |
|---|---|---|
| void validate(UDFParameterValidator validator) throws Exception | 初始化前验证用户输入的参数是否合法 | 否 |
| void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception | 初始化方法,解析参数、配置访问策略和输出类型、创建资源 | 是 |
| Object transform(Row row) throws Exception | 按行处理数据(MappableRowByRow 策略),Row 输入、Object 输出 | 四选一 |
| void transform(Column[] columns, ColumnBuilder builder) throws Exception | 批量处理数据(MappableRowByRow 策略),Column[] 输入、ColumnBuilder 输出 | 四选一 |
| void transform(Row row, PointCollector collector) throws Exception | 按行处理数据(RowByRow 策略),Row 输入、PointCollector 输出 | 四选一 |
| void transform(RowWindow rowWindow, PointCollector collector) throws Exception | 按窗口处理数据(滑动时间/大小窗口等策略),RowWindow 输入、PointCollector 输出 | 四选一 |
| void terminate(PointCollector collector) throws Exception | 所有 transform 执行完后调用,输出最终结果 | 否 |
| void beforeDestroy() | 结束方法,释放资源 | 否 |
方法调用顺序
一个 UDTF 实例的生命周期里,方法调用顺序是固定的:
- validate(可选)
- beforeStart
- 某个 transform 方法(根据访问策略选择)
- terminate(可选)
- beforeDestroy
这里要注意:每次执行 UDTF 查询,框架都会新建一个 UDF 实例,查询结束就销毁。所以不同查询的 UDF 实例数据是隔离的,不用担心并发影响,放心维护内部状态就行。
接口详细介绍
-
validate 方法:可以验证输入序列的数量、类型,检查用户传入的属性,或者做自定义逻辑验证。比如限制必须输入 2 个 INT64 类型的序列。
-
beforeStart 方法:核心是解析参数和配置运行信息,还能创建外部链接、打开文件等资源。
- UDFParameters:解析 SQL 里 UDF 的参数(包括序列和键值对属性)。比如
SELECT UDF(s1, s2, 'key1'='iotdb', 'key2'='123.45') FROM root.sg.d;,可以这样获取参数:void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) throws Exception { String stringValue = parameters.getString("key1"); // 结果是 iotdb Float floatValue = parameters.getFloat("key2"); // 结果是 123.45 Double doubleValue = parameters.getDouble("key3"); // 结果是 null int intValue = parameters.getIntOrDefault("key4", 678); // 结果是 678 // 后续处理... } - UDTFConfigurations:必须用它指定数据访问策略和输出数据类型。比如:
configurations .setAccessStrategy(new RowByRowAccessStrategy()) // 设置访问策略 .setOutputDataType(Type.INT32); // 设置输出类型为 INT32
- UDFParameters:解析 SQL 里 UDF 的参数(包括序列和键值对属性)。比如
-
setAccessStrategy 策略说明:选择的策略决定了框架会调用哪个 transform 方法,也可以根据参数动态选策略,实现多个 transform 方法。
访问策略 描述 对应的 transform 方法 MappableRowByRowStrategy 标量函数,一行输入对应一行输出,可用于 SELECT、WHERE 等子句 Object transform(Row row) 或 void transform(Column[] columns, ColumnBuilder builder) RowByRowAccessStrategy 逐行处理,一行输入可输出多行,多序列按时间对齐 void transform(Row row, PointCollector collector) SlidingTimeWindowAccessStrategy 滑动时间窗口处理,窗口内包含多行数据 void transform(RowWindow rowWindow, PointCollector collector) SlidingSizeWindowAccessStrategy 固定行数窗口处理(最后一个窗口可能不足行数) void transform(RowWindow rowWindow, PointCollector collector) SessionTimeWindowAccessStrategy 会话窗口处理,时间间隔≤sessionGap 归为一组 void transform(RowWindow rowWindow, PointCollector collector) StateWindowAccessStrategy 状态窗口处理,数值变化≤delta 归为一组(仅支持单列输入) void transform(RowWindow rowWindow, PointCollector collector) -
setOutputDataType 类型对应:设置的输出类型要和 transform 里输出的数据类型匹配,对应关系如下:
输出类型 支持的输出数据类型 INT32 int INT64 long FLOAT float DOUBLE double BOOLEAN boolean TEXT java.lang.String、org.apache.iotdb.udf.api.type.Binary
UDTF 实现示例
-
示例 1:MappableRowByRow 策略(Row 输入):两列 INT64 序列相加,一行输入对应一行输出
import org.apache.iotdb.udf.api.UDTF; import org.apache.iotdb.udf.api.access.Row; import org.apache.iotdb.udf.api.customizer.config.UDTFConfigurations; import org.apache.iotdb.udf.api.customizer.parameter.UDFParameterValidator; import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters; import org.apache.iotdb.udf.api.customizer.strategy.MappableRowByRowAccessStrategy; import org.apache.iotdb.udf.api.type.Type; public class Adder implements UDTF { private Type dataType; @Override public void validate(UDFParameterValidator validator) throws Exception { validator .validateInputSeriesNumber(2) // 限制输入2个序列 .validateInputSeriesDataType(0, Type.INT64) // 第一个序列是 INT64 .validateInputSeriesDataType(1, Type.INT64); // 第二个序列是 INT64 } @Override public void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) { dataType = parameters.getDataType(0); configurations .setAccessStrategy(new MappableRowByRowAccessStrategy()) .setOutputDataType(dataType); } @Override public Object transform(Row row) throws Exception { return row.getLong(0) + row.getLong(1); // 两列数据相加 } } -
示例 2:MappableRowByRow 策略(Column 批量输入):批量处理多行数据,性能更好
import org.apache.iotdb.tsfile.read.common.block.column.Column; import org.apache.iotdb.tsfile.read.common.block.column.ColumnBuilder; import org.apache.iotdb.udf.api.UDTF; import org.apache.iotdb.udf.api.customizer.config.UDTFConfigurations; import org.apache.iotdb.udf.api.customizer.parameter.UDFParameterValidator; import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters; import org.apache.iotdb.udf.api.customizer.strategy.MappableRowByRowAccessStrategy; import org.apache.iotdb.udf.api.type.Type; public class Adder implements UDTF { private Type type; @Override public void validate(UDFParameterValidator validator) throws Exception { validator .validateInputSeriesNumber(2) .validateInputSeriesDataType(0, Type.INT64) .validateInputSeriesDataType(1, Type.INT64); } @Override public void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) { type = parameters.getDataType(0); configurations.setAccessStrategy(new MappableRowByRowAccessStrategy()).setOutputDataType(type); } @Override public void transform(Column[] columns, ColumnBuilder builder) throws Exception { long[] inputs1 = columns[0].getLongs(); long[] inputs2 = columns[1].getLongs(); int count = columns[0].getPositionCount(); for (int i = 0; i < count; i++) { builder.writeLong(inputs1[i] + inputs2[i]); // 批量计算相加 } } } -
示例 3:RowByRow 策略:两列数据非空时才输出相加结果
import org.apache.iotdb.udf.api.UDTF; import org.apache.iotdb.udf.api.access.Row; import org.apache.iotdb.udf.api.collector.PointCollector; import org.apache.iotdb.udf.api.customizer.config.UDTFConfigurations; import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters; import org.apache.iotdb.udf.api.customizer.strategy.RowByRowAccessStrategy; import org.apache.iotdb.udf.api.type.Type; public class Adder implements UDTF { @Override public void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) { configurations .setOutputDataType(Type.INT64) .setAccessStrategy(new RowByRowAccessStrategy()); } @Override public void transform(Row row, PointCollector collector) throws Exception { if (row.isNull(0) || row.isNull(1)) { return; // 有一个为空就不输出 } collector.putLong(row.getTime(), row.getLong(0) + row.getLong(1)); } } -
示例 4:滑动时间窗口策略:统计每个时间窗口内的数据行数
import org.apache.iotdb.udf.api.UDTF; import org.apache.iotdb.udf.api.access.RowWindow; import org.apache.iotdb.udf.api.collector.PointCollector; import org.apache.iotdb.udf.api.customizer.config.UDTFConfigurations; import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters; import org.apache.iotdb.udf.api.customizer.strategy.SlidingTimeWindowAccessStrategy; import org.apache.iotdb.udf.api.type.Type; public class Counter implements UDTF { @Override public void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) { configurations .setOutputDataType(Type.INT32) .setAccessStrategy(new SlidingTimeWindowAccessStrategy( parameters.getLong("time_interval"), parameters.getLong("sliding_step"), parameters.getLong("display_window_begin"), parameters.getLong("display_window_end"))); } @Override public void transform(RowWindow rowWindow, PointCollector collector) throws Exception { if (rowWindow.windowSize() != 0) { collector.putInt(rowWindow.windowStartTime(), rowWindow.windowSize()); // 输出窗口起始时间和行数 } } } -
示例 5:terminate 方法:输出序列中的最大值点(需遍历所有数据后计算)
import org.apache.iotdb.udf.api.UDTF; import org.apache.iotdb.udf.api.access.Row; import org.apache.iotdb.udf.api.collector.PointCollector; import org.apache.iotdb.udf.api.customizer.config.UDTFConfigurations; import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters; import org.apache.iotdb.udf.api.customizer.strategy.RowByRowAccessStrategy; import org.apache.iotdb.udf.api.type.Type; public class Max implements UDTF { private Long time; private int value; @Override public void beforeStart(UDFParameters parameters, UDTFConfigurations configurations) { configurations .setOutputDataType(Type.INT32) .setAccessStrategy(new RowByRowAccessStrategy()); } @Override public void transform(Row row, PointCollector collector) { if (row.isNull(0)) { return; } int candidateValue = row.getInt(0); if (time == null || value < candidateValue) { time = row.getTime(); value = candidateValue; // 记录当前最大值和对应时间 } } @Override public void terminate(PointCollector collector) throws Exception { if (time != null) { collector.putInt(time, value); // 所有数据处理完后,输出最大值 } } }
4.3 UDAF(User Defined Aggregation Function)
开发 UDAF 需要两个类:State 类(存储聚合状态)和 UDAF 类(实现聚合逻辑)。
State 类
要实现 org.apache.iotdb.udf.api.State 接口,负责状态的初始化、序列化和反序列化。
| 接口定义 | 描述 | 是否必须 |
|---|---|---|
| void reset() | 重置状态为初始值(框架会复用 State 对象) | 是 |
| byte[] serialize() | 将状态序列化为二进制(用于分布式节点间传递) | 是 |
| void deserialize(byte[] bytes) | 将二进制反序列化为状态(需和序列化顺序一致) | 是 |
示例:求平均数的 State 类
import java.nio.ByteBuffer;
import org.apache.iotdb.udf.api.State;
class AvgState implements State {
double sum; // 总和
long count; // 数据条数
@Override
public void reset() {
sum = 0;
count = 0; // 初始化为 0
}
@Override
public byte[] serialize() {
ByteBuffer buffer = ByteBuffer.allocate(Double.BYTES + Long.BYTES);
buffer.putDouble(sum);
buffer.putLong(count);
return buffer.array(); // 序列化 sum 和 count
}
@Override
public void deserialize(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.wrap(bytes);
sum = buffer.getDouble();
count = buffer.getLong(); // 反序列化,顺序和序列化一致
}
}
UDAF 类
要实现 org.apache.iotdb.udf.api.UDAF 接口,实现聚合的核心逻辑。
| 接口定义 | 描述 | 是否必须 |
|---|---|---|
| void validate(UDFParameterValidator validator) throws Exception | 验证输入参数合法性(和 UDTF 一致) | 否 |
| void beforeStart(UDFParameters parameters, UDAFConfigurations configurations) throws Exception | 初始化方法,解析参数、设置输出类型 | 是 |
| State createState() | 创建并初始化 State 对象 | 是 |
| void addInput(State state, Column[] columns, BitMap bitMap) | 批量更新 State(处理输入数据) | 是 |
| void combineState(State state, State rhs) | 合并两个 State(分布式场景用) | 是 |
| void outputFinal(State state, ResultValue resultValue) | 计算最终聚合结果 | 是 |
| void beforeDestroy() | 结束方法,释放资源 | 否 |
方法调用顺序
UDAF 实例的生命周期调用顺序:
- createState
- validate(可选)
- beforeStart
- addInput(多次调用,处理数据)
- combineState(分布式场景可能多次调用)
- outputFinal(每个组调用一次)
- beforeDestroy
和 UDTF 一样,每次查询都会新建 UDAF 实例,数据隔离,不用担心并发问题。
UDAF 实现示例
以求平均数(avg)为例,完整实现:
import org.apache.iotdb.udf.api.UDAF;
import org.apache.iotdb.udf.api.State;
import org.apache.iotdb.udf.api.customizer.config.UDAFConfigurations;
import org.apache.iotdb.udf.api.customizer.parameter.UDFParameterValidator;
import org.apache.iotdb.udf.api.customizer.parameter.UDFParameters;
import org.apache.iotdb.udf.api.type.Type;
import org.apache.iotdb.tsfile.read.common.BitMap;
import org.apache.iotdb.tsfile.read.common.block.column.Column;
import org.apache.iotdb.udf.api.result.ResultValue;
// 状态类
class AvgState implements State {
double sum;
long count;
@Override
public void reset() {
sum = 0;
count = 0;
}
@Override
public byte[] serialize() {
ByteBuffer buffer = ByteBuffer.allocate(Double.BYTES + Long.BYTES);
buffer.putDouble(sum);
buffer.putLong(count);
return buffer.array();
}
@Override
public void deserialize(byte[] bytes) {
ByteBuffer buffer = ByteBuffer.wrap(bytes);
sum = buffer.getDouble();
count = buffer.getLong();
}
}
// UDAF 主类
public class AvgUDAF implements UDAF {
@Override
public void validate(UDFParameterValidator validator) throws Exception {
validator.validateInputSeriesNumber(1); // 只允许输入1个序列
}
@Override
public void beforeStart(UDFParameters parameters, UDAFConfigurations configurations) {
configurations.setOutputDataType(Type.DOUBLE); // 输出类型为 DOUBLE
}
@Override
public State createState() {
return new AvgState(); // 创建状态对象
}
@Override
public void addInput(State state, Column[] columns, BitMap bitMap) {
AvgState avgState = (AvgState) state;
Column dataColumn = columns[0]; // 第一个列是数据列(最后一列是时间列,这里不用)
int count = dataColumn.getPositionCount();
for (int i = 0; i < count; i++) {
// 跳过被过滤的数据和空值
if (bitMap != null && !bitMap.isMarked(i)) continue;
if (!dataColumn.isNull(i)) {
avgState.sum += dataColumn.getDouble(i);
avgState.count++;
}
}
}
@Override
public void combineState(State state, State rhs) {
AvgState avgState = (AvgState) state;
AvgState avgRhs = (AvgState) rhs;
avgState.sum += avgRhs.sum; // 合并总和
avgState.count += avgRhs.count; // 合并数据条数
}
@Override
public void outputFinal(State state, ResultValue resultValue) {
AvgState avgState = (AvgState) state;
if (avgState.count != 0) {
resultValue.setDouble(avgState.sum / avgState.count); // 计算平均值
} else {
resultValue.setNull(); // 没有数据时返回空
}
}
}
4.4 完整 Maven 项目示例
如果用 Maven 管理项目,可以参考官方的 udf-example 示例项目,直接在 GitHub 上就能找到。
5. 为 IoTDB 贡献通用的内置 UDF 函数
如果你的 UDF 很通用,想分享给社区其他用户,可以按下面的步骤贡献:
5.1 前提条件
- 通用性:你的 UDF 要能在多个业务场景中被广泛使用,有复用价值;
- 可用性:已经完成测试,能在生产环境正常运行。
不确定是否符合通用性?可以发邮件到 [email protected],或者在 GitHub 上创建 ISSUE 讨论。
5.2 贡献清单
要准备三样东西:UDF 源代码、测试用例、使用说明。
5.3 贡献内容
-
源代码:
- 在
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin下创建 UDF 主类和辅助类; - 在
iotdb-core/node-commons/src/main/java/org/apache/iotdb/commons/udf/builtin/BuiltinTimeSeriesGeneratingFunction.java中注册你的 UDF。
- 在
-
测试用例:至少要写集成测试,在
integration-test/src/test/java/org/apache/iotdb/db/it/udf下新增测试类。 -
使用说明:
- 要包含 UDF 名称、作用、必填参数、适用场景、使用示例;
- 需准备中英文两个版本,分别添加到
docs/zh/UserGuide/Operation Manual/DML Data Manipulation Language.md和docs/UserGuide/Operation Manual/DML Data Manipulation Language.md中。
-
提交 PR:准备好后,在 GitHub 上提交 Pull Request,具体流程看 IoTDB 的贡献指南。PR 评审通过并合并后,你的 UDF 就正式加入 IoTDB 社区了!
6. 常见问题
问:怎么修改已经注册的 UDF?
答:假设 UDF 名称是 example,全类名是 org.apache.iotdb.udf.UDTFExample,由 example.jar 引入,步骤如下:
- 先卸载:
DROP FUNCTION example; - 删除集群所有节点 ext/udf 目录下的 example.jar;
- 修改 UDF 代码后重新打包(JAR 名可不变);
- 把新 JAR 包放到所有节点的 ext/udf 目录;
- 重新注册:
CREATE FUNCTION example AS "org.apache.iotdb.udf.UDTFExample"。
🌐 附:IoTDB的各大版本
📄 Apache IoTDB 是一款工业物联网时序数据库管理系统,采用端边云协同的轻量化架构,支持一体化的物联网时序数据收集、存储、管理与分析 ,具有多协议兼容、超高压缩比、高通量读写、工业级稳定、极简运维等特点。
| 版本 | IoTDB 二进制包 | IoTDB 源代码 | 发布说明 |
|---|---|---|---|
| 2.0.5 | - All-in-one - AINode - SHA512 - ASC | - 源代码 - SHA512 - ASC | release notes |
| 1.3.5 | - All-in-one - AINode - SHA512 - ASC | - 源代码 - SHA512 - ASC | release notes |
| 0.13.4 | - All-in-one - Grafana 连接器 - Grafana 插件 - SHA512 - ASC | - 源代码 - SHA512 - ASC | release notes |
✨ 去获取:https://archive.apache.org/dist/iotdb/
联系博主
xcLeigh 博主,全栈领域优质创作者,博客专家,目前,活跃在CSDN、微信公众号、小红书、知乎、掘金、快手、思否、微博、51CTO、B站、腾讯云开发者社区、阿里云开发者社区等平台,全网拥有几十万的粉丝,全网统一IP为 xcLeigh。希望通过我的分享,让大家能在喜悦的情况下收获到有用的知识。主要分享编程、开发工具、算法、技术学习心得等内容。很多读者评价他的文章简洁易懂,尤其对于一些复杂的技术话题,他能通过通俗的语言来解释,帮助初学者更好地理解。博客通常也会涉及一些实践经验,项目分享以及解决实际开发中遇到的问题。如果你是开发领域的初学者,或者在学习一些新的编程语言或框架,关注他的文章对你有很大帮助。
亲爱的朋友,无论前路如何漫长与崎岖,都请怀揣梦想的火种,因为在生活的广袤星空中,总有一颗属于你的璀璨星辰在熠熠生辉,静候你抵达。
愿你在这纷繁世间,能时常收获微小而确定的幸福,如春日微风轻拂面庞,所有的疲惫与烦恼都能被温柔以待,内心永远充盈着安宁与慰藉。
至此,文章已至尾声,而您的故事仍在续写,不知您对文中所叙有何独特见解?期待您在心中与我对话,开启思想的新交流。
💞 关注博主 🌀 带你实现畅游前后端!
🏰 大屏可视化 🌀 带你体验酷炫大屏!
💯 神秘个人简介 🌀 带你体验不一样得介绍!
🥇 从零到一学习Python 🌀 带你玩转Python技术流!
🏆 前沿应用深度测评 🌀 前沿AI产品热门应用在线等你来发掘!
💦 注:本文撰写于CSDN平台,作者:xcLeigh(所有权归作者所有) ,https://xcleigh.blog.csdn.net/,如果相关下载没有跳转,请查看这个地址,相关链接没有跳转,皆是抄袭本文,转载请备注本文原地址。

📣 亲,码字不易,动动小手,欢迎 点赞 ➕ 收藏,如 🈶 问题请留言(或者关注下方公众号,看见后第一时间回复,还有海量编程资料等你来领!),博主看见后一定及时给您答复 💌💌💌
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/weixin_43151418/article/details/155187851




