源自清华的 IoTDB v2.0 新增支持表模型
时序数据库在能源电力、航空航天、交通运输、钢铁冶炼、物联网、边缘计算等领域有这广泛的应用。以电力行业为例,IoTDB 凭借其集群高可用性、低流量数据同步、数据跨网闸支持以及卓越的性能,为企业提供国产化、自主可控的时序数据管理解决方案。它不仅帮助企业应对大规模时序数据管理的挑战,还推动了传统能源与可再生能源的高效管理和整合。

时序数据库
时间序列数据库,是一种针对时间序列数据优化的数据库管理系统,每个条目都与一个时间戳相关联。例如,物联网中的传感器、智能电表或 RFID 标签产生的数据,以及高频股票交易系统的股票行情,都可以视为时间序列数据。时序数据库旨在高效收集、存储和查询具有高交易量的时间序列数据。
常见的产品有:InfluxDB、TimescaleDB、OpenTSDB、QuestDB、浪潮 KWDB,以及 Apache IoTDB。
| 产品名称 | 产品特点 | 开源协议 | 编程语言 |
|---|---|---|---|
| InfluxDB | 优秀的时序数据库产品,适合大量数据实时写入,拥有大量的用户和插件生态,可以快速集成监控、IoT 等场景。 | 开源,Apache 2.0 协议 | Rust |
| TimescaleDB | 基于 PostgreSQL,支持标准 SQL 查询,兼容 PG 生态,学习曲线平滑。 | 开源,Apache 2.0 协议 | C |
| OpenTSDB | 基于 HBase 的分布式时序数据库,支持高并发写入和大规模数据存储,可扩展性高。 | 开源,LGPLv2.1 和 GPLv3 协议 | Java |
| QuestDB | 基于内存优化和列式存储,适用于中小数据场景,支持标准 SQL。 | 开源,Apache 2.0 协议 | Java |
| IoTDB | 源自清华的一款专门面向物联网数据管理的国产开源数据库。 | 开源,Apache 2.0 协议 | Java |
IoTDB
我们之前介绍过 Apache IoTDB v1.3 的相关内容,这里再重温几个关键基础概念。



IoTDB 集群包括三种节点(进程)。
- ConfigNode(管理节点):管理集群的节点信息、配置信息、用户权限、元数据、分区信息等,负责分布式操作的调度和负载均衡,所有 ConfigNode 之间互为全量备份。
- DataNode(数据节点):服务客户端请求,负责数据的存储和计算。
- AINode(分析节点):负责提供机器学习能力,支持注册已训练好的机器学习模型,并通过 SQL 调用模型进行推理,目前已内置自研时序大模型和常见的机器学习算法(如预测与异常检测)。

数据模型的重点概念。
- 元数据(Schema):数据库的数据模型信息,即树形结构或表结构。包括测点的名称、数据类型等定义。
- 设备(Device):对应一个实际场景中的物理设备,通常包含多个测点。
- 测点(Timeseries):又名:物理量、时间序列、时间线、点位、信号量、指标、测量值等。测点是多个数据点按时间戳递增排列形成的一个时间序列。通常一个测点代表一个采集点位,能够定期采集所在环境的物理量。

IoTDB v2.0.1-beta 发布
2025 年 2 月 16 日,Apache IoTDB v2.0.1-beta 版本发布,新增多项新特性并修复了若干问题。
新特性概览如下。
- 表模型:IoTDB 引入了新的表模型,支持标准 SQL 查询语法,包括 SELECT、WHERE、JOIN、GROUP BY、ORDER BY、LIMIT 子句和子查询等。
- 数据查询:表模型支持多种函数和运算符,包括逻辑运算符、数学函数、时间序列特有的函数 DIFF 等。
- 数据查询:表模型和树模型的数据库互不可见,用户可以根据需求选择合适的模型。
- 数据查询:用户可以通过配置项通过 URI 控制 UDF、PipePlugin、Trigger、AINode 的加载,加载 JAR 包。
- 存储引擎:表模型支持通过 Session 接口进行数据提取,Session 接口支持自动创建元数据。
- 存储引擎:Python 客户端现在支持四种新的数据类型:String、Blob、Date、Timestamp。
- 存储引擎:优化了同类型合并任务优先级的比较规则。
- 数据同步:支持在发送端指定接收端的认证信息。
- 流处理模块:TsFile Load 现在支持表模型。
- 流处理模块:Pipe 现在支持表模型。
- 系统管理:Benchmark 工具适配支持表模型。
- 系统管理:Benchmark 工具现在支持 String、Blob、Date、Timestamp 四种新数据类型。
- 系统管理:增强 DataNode 缩容的稳定性。
- 系统管理:现在允许用户在只读模式下执行 drop database 操作。
- 脚本和工具:扩展 import-data/export-data 脚本,支持新数据类型(字符串、大二进制对象、日期、时间戳)。
- 脚本和工具:迭代 import-data/export-data 脚本,支持 TsFile、CSV、SQL 三种数据的导入导出。
- 生态集成:支持 Kubernetes Operator。
IoTDB v2.0 表模型详解
从 IoTDB v2.0 开始,IoTDB 支持两种时序数据模型(SQL语法),树模型和表模型。
树模型
树模型以测点为对象进行管理,每个测点对应一条时间序列,测点名按.分割可形成一个树形目录结构,与物理世界一一对应,对测点的读写操作简单直观。
表模型
表模型推荐为每类设备创建一张表,同类设备的物理量采集都具备一定共性(如都采集温度和湿度物理量),数据分析灵活丰富。特点是,便于使用标准 SQL 进行分析,适用于设备数据分析或从其他数据库迁移至 IoTDB 的场景。
以下是对表模型的具体建模演示,包括创建设备表、写入数据和查询数据。为验证基本功能,我们使用单点容器,容器内启动一个管理节点和一个数据节点(1C1D)。
表模型演示
1. 启动单点容器
podman pull apache/iotdb:2.0.1-beta-standalone
podman run -it 34485072113d bash
2. 启动 IoTDB 服务并连接到数据库
root@d2fc22531f7b:/iotdb/sbin# ./start-all.sh
The iotdb-cluster.properties file only contains default settings. It will start 1C1D.
Execute start-standalone.sh finished, you can see more details in the logs of confignode and datanode
root@d2fc22531f7b:/iotdb/sbin# ./start-cli.sh
---------------------
Starting IoTDB Cli
---------------------
_____ _________ ______ ______
|_ _| | _ _ ||_ _ `.|_ _ \
| | .--.|_/ | | \_| | | `. \ | |_) |
| | / .'`\ \ | | | | | | | __'.
_| |_| \__. | _| |_ _| |_.' /_| |__) |
|_____|'.__.' |_____| |______.'|_______/ version 2.0.1-beta (Build: 5f31648)
Successfully login at 127.0.0.1:6667
IoTDB> show cluster
+------+----------+-------+---------------+------------+----------+---------+
|NodeID| NodeType| Status|InternalAddress|InternalPort| Version|BuildInfo|
+------+----------+-------+---------------+------------+----------+---------+
| 0|ConfigNode|Running| 127.0.0.1| 10710|2.0.1-beta| 5f31648|
| 1| DataNode|Running| 127.0.0.1| 10730|2.0.1-beta| 5f31648|
+------+----------+-------+---------------+------------+----------+---------+
Total line number = 2
It costs 0.053s
IoTDB>
3. 切换到表模型
默认情况下,客户端连接时使用树模型。如果需要使用表模型,需要在启动客户端时指定 SQL 方言。
root@d2fc22531f7b:/iotdb/sbin# ./start-cli.sh -sql_dialect table
---------------------
Starting IoTDB Cli
---------------------
_____ _________ ______ ______
|_ _| | _ _ ||_ _ `.|_ _ \
| | .--.|_/ | | \_| | | `. \ | |_) |
| | / .'`\ \ | | | | | | | __'.
_| |_| \__. | _| |_ _| |_.' /_| |__) |
|_____|'.__.' |_____| |______.'|_______/ version 2.0.1-beta (Build: 5f31648)
Successfully login at 127.0.0.1:6667
IoTDB>

不过 start-cli.sh 提供了两种帮助提示(--help,-help),且内容输出不同,需要注意区分。
4. 创建数据库
创建一个名为 mydb 的数据库,并将数据库的 TTL 时间设置为 1 年。
IoTDB> CREATE DATABASE IF NOT EXISTS mydb with (TTL=31536000000);
Msg: The statement is executed successfully.
IoTDB> use mydb;
Msg: The statement is executed successfully.
IoTDB:mydb>
5. 查看数据库
查看所有数据库和数据库的属性信息。
IoTDB:mydb> SHOW DATABASES DETAILS
+------------------+-----------+-----------------------+---------------------+---------------------+--------------------+------------------+
| Database| TTL(ms)|SchemaReplicationFactor|DataReplicationFactor|TimePartitionInterval|SchemaRegionGroupNum|DataRegionGroupNum|
+------------------+-----------+-----------------------+---------------------+---------------------+--------------------+------------------+
|information_schema| INF| null| null| null| null| null|
| mydb|31536000000| 1| 1| 604800000| 0| 0|
+------------------+-----------+-----------------------+---------------------+---------------------+--------------------+------------------+
Total line number = 2
It costs 0.008s
6. 创建测试表
在创建表时,需要注意:
- 可以不指定时间列(
TIME),IoTDB 会自动添加该列。 - 列的类别可以省略,默认为
FIELD。当列的类别为TAG或ATTRIBUTE时,数据类型需为 STRING`(可省略)。 - 表的 TTL 默认为其所在数据库的 TTL。

CREATE TABLE IF NOT EXISTS t_t1 (
region STRING TAG,
plant_id TAG,
device_id STRING TAG,
model_id STRING ATTRIBUTE,
maintenance ATTRIBUTE,
temperature FLOAT FIELD,
humidity FLOAT,
status Boolean FIELD,
arrival_time TIMESTAMP FIELD
);
CREATE TABLE IF NOT EXISTS "表1" (
"地区" STRING TAG,
"厂号" TAG,
"设备号" STRING TAG,
"型号" STRING ATTRIBUTE,
"维护周期" ATTRIBUTE,
"温度" FLOAT FIELD,
"湿度" FLOAT,
"状态" Boolean FIELD,
"到达时间" TIMESTAMP FIELD
);
查看数据库中的表,并查看"表1"的详细信息。
IoTDB:mydb> show tables;
+---------+-----------+
|TableName| TTL(ms)|
+---------+-----------+
| 表1|31536000000|
| t_t1|31536000000|
+---------+-----------+
Total line number = 2
It costs 0.020s
IoTDB:mydb> desc "表1" details;
+----------+---------+---------+------+
|ColumnName| DataType| Category|Status|
+----------+---------+---------+------+
| time|TIMESTAMP| TIME| USING|
| 地区| STRING| TAG| USING|
| 厂号| STRING| TAG| USING|
| 设备号| STRING| TAG| USING|
| 型号| STRING|ATTRIBUTE| USING|
| 维护周期| STRING|ATTRIBUTE| USING|
| 温度| FLOAT| FIELD| USING|
| 湿度| FLOAT| FIELD| USING|
| 状态| BOOLEAN| FIELD| USING|
| 到达时间|TIMESTAMP| FIELD| USING|
+----------+---------+---------+------+
Total line number = 10
It costs 0.008s
7. 写入数据
对测试表分别插入单条数据和多条数据。
INSERT INTO t_t1 (region, plant_id, device_id, model_id, maintenance, temperature, humidity, status, arrival_time)
VALUES (1001,1,1,1,10,80.0,60.0,1,now());
INSERT INTO t_t1 (time, region, plant_id, device_id, model_id, maintenance, temperature, humidity, status, arrival_time)
VALUES (now(),1001,1,2,2,11,81.0,61.0,0,now())
,(now(),1002,1,3,3,13,83.0,63.0,0,now())
,(now(),1002,2,4,4,14,null,null,0,now())
;
INSERT INTO "表1" ("地区", "厂号", "设备号", "型号", "维护周期", "温度", "湿度", "状态", "到达时间")
VALUES (1001,1,1,1,10,80.0,60.0,1,now());
INSERT INTO "表1" (time, "地区", "厂号", "设备号", "型号", "维护周期", "温度", "湿度", "状态", "到达时间")
VALUES (now(),1001,1,2,2,11,81.0,61.0,0,now())
,(now(),1002,1,3,3,13,83.0,63.0,0,now())
,(now(),1002,2,4,4,14,null,null,0,now())
;
8. 查询表数据
IoTDB:mydb> select * from t_t1;
+------------------------+------+--------+---------+--------+-----------+-----------+--------+------+------------------------+
| time|region|plant_id|device_id|model_id|maintenance|temperature|humidity|status| arrival_time|
+------------------------+------+--------+---------+--------+-----------+-----------+--------+------+------------------------+
|2025-02-20T09:21:53.592Z| 1002| 2| 4| 4| 14| null| null| false|2025-02-20T09:21:53.592Z|
|2025-02-20T09:21:53.592Z| 1001| 1| 2| 2| 11| 81.0| 61.0| false|2025-02-20T09:21:53.592Z|
|2025-02-20T09:21:53.592Z| 1002| 1| 3| 3| 13| 83.0| 63.0| false|2025-02-20T09:21:53.592Z|
|2025-02-20T09:21:05.945Z| 1001| 1| 1| 1| 10| 80.0| 60.0| true|2025-02-20T09:21:05.944Z|
+------------------------+------+--------+---------+--------+-----------+-----------+--------+------+------------------------+
Total line number = 4
It costs 0.043s
IoTDB:mydb> table "表1";
+------------------------+----+----+------+----+--------+----+----+-----+------------------------+
| time|地区|厂号|设备号|型号|维护周期|温度|湿度| 状态| 到达时间|
+------------------------+----+----+------+----+--------+----+----+-----+------------------------+
|2025-02-20T09:26:34.090Z|1002| 2| 4| 4| 14|null|null|false|2025-02-20T09:26:34.090Z|
|2025-02-20T09:26:34.090Z|1001| 1| 2| 2| 11|81.0|61.0|false|2025-02-20T09:26:34.090Z|
|2025-02-20T09:26:34.090Z|1002| 1| 3| 3| 13|83.0|63.0|false|2025-02-20T09:26:34.090Z|
|2025-02-20T09:26:28.987Z|1001| 1| 1| 1| 10|80.0|60.0| true|2025-02-20T09:26:28.987Z|
+------------------------+----+----+------+----+--------+----+----+-----+------------------------+
Total line number = 4
It costs 0.039s

9. 数据分析
按厂号分组,查询平均温度,最大维护周期,并对结果排序。
SELECT "厂号", ROUND(AVG("温度")) AS avg_temp, MAX("维护周期") AS max_mt
FROM "表1"
WHERE "地区" in ('1001', '1002')
GROUP BY "厂号"
ORDER BY max_mt DESC
LIMIT 10;
预期输出:
+----+--------+------+
|厂号|avg_temp|max_mt|
+----+--------+------+
| 2| null| 14|
| 1| 81.0| 13|
+----+--------+------+
Total line number = 2
It costs 0.038s
10. 时序特色函数 DIFF
DIFF 函数用于计算当前行与上一行的差值。对于第一行,由于没有前一行数据,因此永远返回 NULL。
IoTDB:mydb> SELECT time, DIFF(temperature) AS diff_temp
> FROM t_t1 ORDER BY device_id;
+------------------------+---------+
| time|diff_temp|
+------------------------+---------+
|2025-02-20T09:21:05.945Z| null|
|2025-02-20T09:21:53.592Z| 1.0|
|2025-02-20T09:21:53.592Z| 2.0|
|2025-02-20T09:21:53.592Z| null|
+------------------------+---------+
Total line number = 4
It costs 0.035s
总结
Apache IoTDB v2.0 通过引入重磅新特性“表模型”,不仅进一步提升了其在物联网和工业大数据领域的竞争力,还为企业提供了更灵活、高效的数据管理方案。表模型支持标准 SQL 查询语法,使得数据分析更加便捷,同时兼容两种模型设计,可满足不同用户的需求。需要注意的是,Tree 和 Table 两种模型在开源版只能分开使用,如需双模型结合使用,推荐升级到基于 Apache IoTDB 的企业版数据库 TimechoDB。




