[时序数据库] Apache IoTDB 使用指南
0 序
- 如无特殊说明,本篇基于 apache iotdb 2.0.11 进行试验。
1 使用指南
环境要求
- JDK:需安装 Java 运行环境,推荐 JDK 17(V1.3.2.2 及之后版本;老版本 JDK 部分场景性能有问题,且 DataNode 可能 stop 不掉)。
- 系统:Linux、Windows、macOS 及其他 Unix-like 系统均支持。
- 资源规划(参考官网):单机版 50W 序列以内建议 12G–24G 内存、1 节点;更大规模可上双活(2 节点)或分布式(≥3 节点)。
- 端口:ConfigNode 占用 10710/10720;DataNode 占用 6667、10730、10740、10750、10760、9090、9190、3000 等,部署前需确保未被占用。
安装部署
Linux/Windows 单机版 | 亲测
Windows 亲测
- 获取安装包:从 https://iotdb.apache.org/zh/Download/ 下载最新 All-in-one 二进制包(当前为 2.0.11)。
https://www.apache.org/dyn/closer.cgi/iotdb/2.0.11/apache-iotdb-2.0.11-all-bin.zip
1. Apache IoTDB 2.x 要求 JDK 11+。
1.1 执行`echo $JAVA_HOME`验证:如果 `JAVA_HOME` 为空或指向 JDK 8,脚本里的 `$JAVA_HOME/bin/java` 或 classpath 拼接会出错。
1.2 执行 `java -version`验证: JDK版本
2. 确认 JDK 的 lib 目录里 CLI jar 存在
2.1 执行`ls -lh lib/ | grep -i cli`
2.1 应看到类似 `iotdb-cli-2.0.11.jar`(或在 `lib/` 下的 cli 相关 jar)。
- 如果【没有】这个 jar,说明解压不完整,重新解压安装包。
- 如果【有】,继续下一步。
...
- 解压(以 Linux 为例):
tar -zxvf apache-iotdb-2.0.11-all-bin.zip
cd apache-iotdb-2.0.11
-
内存配置(可选):在
conf/confignode-env.sh、conf/datanode-env.sh中调整ON_HEAP_MEMORY、OFF_HEAP_MEMORY控制堆内/堆外内存(默认约为系统内存 30%)。 -
启动:
# 启动 ConfigNode sbin/start-confignode.sh # 启动 DataNode sbin/start-datanode.shWindows 下对应使用
sbin/windows/start-confignode.bat、sbin/windows/start-datanode.bat。 -
验证:通过 CLI 客户端连接
Windows(Git-Bash)为例:
$ cd /d/Programs/Apache-IoTDB/apache-iotdb-2.0.11-all-bin/
$ ./sbin/windows/start-cli.bat -h 127.0.0.1 -p 6667
---------------------
Starting IoTDB Cli
---------------------
_____ _________ ______ ______
|_ _| | _ _ ||_ _ `.|_ _ \
| | .--.|_/ | | \_| | | `. \ | |_) |
| | / .'`\ \ | | | | | | | __'.
_| |_| \__. | _| |_ _| |_.' /_| |__) |
|_____|'.__.' |_____| |______.'|_______/ version 2.0.11 (Build: 7c0de06)
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.11| 7c0de06|
| 1| DataNode|Running| 127.0.0.1| 10730| 2.0.11| 7c0de06|
+------+----------+-------+---------------+------------+-------+---------+
Total line number = 2
It costs 0.075s
IoTDB>
Docker Compose 方式(集群版/非Standalone版) | 亲测
- 总体思路
Docker:
docker network create --driver=bridge --subnet=172.18.0.0/16 --gateway=172.18.0.1 iotdb,再用 docker-compose 编排 ConfigNode + DataNode。
- 推荐文档
其他部署方式
- Kubernetes:通过 Helm/编排文件部署,暴露 confignode-svc / datanode-svc。
- 分布式集群:配置 3C3D(3 ConfigNode + ≥3 DataNode),实现高可用与扩展。
- AINode:需额外安装 Python3 及
venv模块(如apt-get install python3.10-venv)。
关键操作
1. 数据库建模(树/表孪生模型)
- 树模型:测点名用
.分割,如root.工厂.设备.传感器。 - 表模型:每类设备创建一张表,字段对应物理量(如温度、湿度)。
2. 写入数据(类 SQL)
-- 建库建表
CREATE DATABASE root.vehicle;
CREATE TABLE vehicle.device (device_id STRING ID, ts TIMESTAMP TIME, temperature FLOAT FIELD, ...);
-- 插入数据
INSERT INTO root.vehicle.device(ts, device_id, temperature) VALUES (now(), 'd1', 36.5);
-- 原生(树模型)写入
INSERT INTO root.工厂.设备.传感器(timestamp, 温度) VALUES (now(), 25.3);
3. 查询数据
-- 原始数据查询
SELECT temperature FROM root.vehicle.device WHERE ts > 2026-01-01;
-- 聚合/降采样
SELECT COUNT(temperature), AVG(temperature) FROM root.vehicle.device
WHERE ts BETWEEN 2026-01-01 AND 2026-01-31 GROUP BY TIME(1d);
-- 最新点/趋势分析
SELECT LATEST(temperature) FROM root.vehicle.device;
4. 周边工具
- IoT-benchmark:基于 Java 的时序数据库基准测试工具。
- 数据导入/导出脚本:
import-csv.sh/export-csv.sh(或export-tsfile.sh),批量导入导出。 - 可视化控制台 / 监控工具:管理集群、查看性能。
5. 应用编程接口
- Java、Python、C/C++、Go/C#/Rest 等多语言客户端,通过 SDK 连接
127.0.0.1:6667。
常见操作-连接管理
查看当前 SQL_DIALECT 模式
IoTDB> SHOW CURRENT_SQL_DIALECT
+-----------------+
|CurrentSqlDialect|
+-----------------+
| TREE|
+-----------------+
Total line number = 1
It costs 0.005s
TREE / TABLE
设置 SQL_DIALECT
SET SQL_DIALECT=TREE; -- 切到树模型空间
SET SQL_DIALECT=TABLE; -- 切到表模型空间
- CLI 连接时也要指定:
start-cli.sh -sql_dialect tree|table。JDBC URL 里加?sql_dialect=table。
客户端登录 By Docker
$ docker exec -it iotdb-datanode start-cli.sh -h 192.168.xxx.xxx -p 6667 -u root -pw root -sql_dialect tree
---------------------
Starting IoTDB Cli
---------------------
_____ _________ ______ ______
|_ _| | _ _ ||_ _ `.|_ _ \
| | .--.|_/ | | \_| | | `. \ | |_) |
| | / .'`\ \ | | | | | | | __'.
_| |_| \__. | _| |_ _| |_.' /_| |__) |
|_____|'.__.' |_____| |______.'|_______/ version 2.0.11 (Build: 7c0de06)
Successfully login at 192.168.xxx.xxx:6667
IoTDB> show cluster;
+------+----------+-------+----------------+------------+-------+---------+
|NodeID| NodeType| Status| InternalAddress|InternalPort|Version|BuildInfo|
+------+----------+-------+----------------+------------+-------+---------+
| 0|ConfigNode|Running|iotdb-confignode| 10710| 2.0.11| 7c0de06|
| 1| DataNode|Running| iotdb-datanode| 10730| 2.0.11| 7c0de06|
+------+----------+-------+----------------+------------+-------+---------+
Total line number = 2
It costs 0.018s
IoTDB> show databases;
...
客户端登录 By 本地CLI
Windows + Git-Bash
xxx@DESKTOP-xxxxx /d/Programs/Apache-loTDB/apache-iotdb-2.0.11-all-bin
$ ./sbin/windows/start-cli.bat -h 192.168.xxx.xxx -p 6667 -sql_dialect table
---------------------
Starting IoTDB Cli
---------------------
_____ _________ ______ ______
|_ _| | _ _ ||_ _ `.|_ _ \
| | .--.|_/ | | \_| | | `. \ | |_) |
| | / .'`\ \ | | | | | | | __'.
_| |_| \__. | _| |_ _| |_.' /_| |__) |
|_____|'.__.' |_____| |______.'|_______/ version 2.0.11 (Build: 7c0de06)
Successfully login at 192.168.xxx.xxx:6667
IoTDB> show databases;
+------------------+-------+-----------------------+---------------------+---------------------+
| Database|TTL(ms)|SchemaReplicationFactor|DataReplicationFactor|TimePartitionInterval|
+------------------+-------+-----------------------+---------------------+---------------------+
|information_schema| INF| null| null| null|
+------------------+-------+-----------------------+---------------------+---------------------+
Total line number = 1
It costs 0.100s
IoTDB> show databases;
...
常见操作-Cluster
查看集群情况
IoTDB> show cluster
+------+----------+-------+---------------+------------+-------+---------+
|NodeID| NodeType| Status|InternalAddress|InternalPort|Version|BuildInfo|
+------+----------+-------+---------------+------------+-------+---------+
| 0|ConfigNode|Running| 127.0.0.1| 10710| 2.0.11| 7c0de06|
| 1| DataNode|Running| 127.0.0.1| 10730| 2.0.11| 7c0de06|
+------+----------+-------+---------------+------------+-------+---------+
Total line number = 2
It costs 0.075s
IoTDB>
常见操作-Database
列出-所有数据库
-
IoTDB 没有"当前所在数据库" 的概念——它不像 MySQL 有
USE db切换当前库的机制,也不存在SELECT DATABASE()这类函数。所有读写都必须写完整路径(从root.开始)。 -
如果想查看数据库相关信息,常用命令如下:
| 需求 | 命令 |
|---|---|
| 查看所有数据库(存储组) | SHOW DATABASES;(旧版:SHOW STORAGE GROUP;) |
| 查看某库下全部序列 | SHOW TIMESERIES root.factory; |
| 查看某库下设备 | SHOW DEVICES root.factory; |
| 查看库参数(TTL、schema 配额等) | SHOW DATABASES root.factory; 会带详细信息 |
- 举例:
IoTDB> SHOW DATABASES; -- 树模型 + 表模型 均兼容
+------------+-----------------------+---------------------+-------------------+---------------------+
| Database|SchemaReplicationFactor|DataReplicationFactor|TimePartitionOrigin|TimePartitionInterval|
+------------+-----------------------+---------------------+-------------------+---------------------+
|root.factory| 1| 1| 0| 604800000|
+------------+-----------------------+---------------------+-------------------+---------------------+
Total line number = 1
It costs 0.008s
IoTDB> SHOW DATABASES root.*; -- 树模型的特有语法
+------------+-----------------------+---------------------+-------------------+---------------------+
| Database|SchemaReplicationFactor|DataReplicationFactor|TimePartitionOrigin|TimePartitionInterval|
+------------+-----------------------+---------------------+-------------------+---------------------+
|root.factory| 1| 1| 0| 604800000|
+------------+-----------------------+---------------------+-------------------+---------------------+
Total line number = 1
It costs 0.005s
如果目的是"我当前建了哪些库、数据存在哪",用
SHOW DATABASES即可。如果你是想在脚本里先确认某库存在再操作,可以先SHOW DATABASES,再对结果做判断。
创建-数据库
-- 先建数据库
-- IoTDB 的数据库名必须以 `root.` 开头。IoTDB 采用树形数据模型,所有路径(包括数据库名)都要从 `root` 根节点开始。
IoTDB> CREATE DATABASE root.factory;
Msg: The statement is executed successfully.
- 旧版本(0.x/ 1.0 之前)语法是
SET STORAGE GROUP TO root.factory;- 新版本(1.0+)统一用
CREATE DATABASE root.factory;- 使用时可带括号指定参数,例如
CREATE DATABASE root.factory WITH (TTL=86400000);Apache IoTDB 的 TTL 参数以毫秒为单位,默认值为
-1(表示永不过期)。
TTL=86400000ms = 86400 秒 = 24 小时 = 1 天也就是说,
root.factory下时间戳早于当前时间 1 天(24h)的数据会被自动清除。
常见换算参考:
| 目标时长 | TTL 值(毫秒) |
|---|---|
| 1 天 | 86400000 |
| 7 天 | 604800000 |
| 30 天 | 2592000000 |
| 永久 | -1(默认) |
切换到指定数据库
USE factory;
统计数据库数量
IoTDB> COUNT DATABASES root.**; -- 树模型
+-----+
|count|
+-----+
| 1|
+-----+
Total line number = 1
It costs 0.016s
Msg: org.apache.iotdb.jdbc.IoTDBSQLException: 700: Error occurred while parsing SQL to physical plan: line 1:0 mismatched input '-' expecting {ALTER, CALL, CLEAR, COUNT, CREATE, DEACTIVATE, DEBUG, DELETE, DROP, EXPLAIN, EXTEND, FLUSH, GRANT, INSERT, KILL
, LIST, LOAD, MIGRATE, RECONSTRUCT, REMOVE, REVOKE, SELECT, SET, SETTLE, SHOW, START, STOP, UNLOAD, UNSET, VERIFY, REPAIR}
删除数据库
//重复删库,在表模型下会报错: IoTDBSQLException: 500: Database factory doesn't exist
//重复删库,在树模型下会报错: IoTDBSQLException: 508: Path [root.factory] does not exist
DELETE DATABASE root.factory; -- 树模型(方法1)
DROP DATABASE root.factory; -- 树模型(方法2)
常见操作-测点(时间序列/TimeSeries)管理 (树模型)
创建-测点
-- 创建测点(完整写法)
CREATE TIMESERIES root.factory.wf01.wt01.status WITH DATATYPE=BOOLEAN, ENCODING=PLAIN;
CREATE TIMESERIES root.factory.wf01.wt01.temperature WITH DATATYPE=FLOAT, ENCODING=RLE;
-- 简化写法
CREATE TIMESERIES root.factory.wf01.wt01.temperature FLOAT ENCODING=RLE;
-- 批量创建对齐时间序列(同一设备多个测点绑一起存,性能更好)
CREATE ALIGNED TIMESERIES root.factory.wf01.GPS(
latitude FLOAT encoding=PLAIN compressor=SNAPPY,
longitude FLOAT encoding=PLAIN compressor=SNAPPY
);
-- 创建【带标签/属性】的测点
CREATE TIMESERIES root.turbine.d1.s1
WITH DATATYPE=FLOAT, ENCODING=RLE, COMPRESSOR=SNAPPY
TAGS(tag1=v1, tag2=v2)
ATTRIBUTES(attr1=v1);
查看测点
-- 查看测点
SHOW TIMESERIES; -- 全部
IoTDB> SHOW TIMESERIES;
+-----------------------------------------+-----+------------+---------+--------+-----------+-------------------------+--------------+--------+------------------+--------+
| Timeseries|Alias| Database| DataType|Encoding|Compression| Tags| Attributes|Deadband|DeadbandParameters|ViewType|
+-----------------------------------------+-----+------------+---------+--------+-----------+-------------------------+--------------+--------+------------------+--------+
| root.turbine.d1.s1| null|root.turbine| FLOAT| RLE| SNAPPY|{"tag1":"v1","tag2":"v2"}|{"attr1":"v1"}| null| null| BASE|
| root.ln.wf02.wt02.status| null| root.ln| BOOLEAN| RLE| LZ4| null| null| null| null| BASE|
| root.ln.wf02.wt02.hardware| null| root.ln| TEXT| PLAIN| LZ4| null| null| null| null| BASE|
| root.sg1.d1.s1| null| root.sg1| DOUBLE| GORILLA| LZ4| null| null| null| null| BASE|
| root.sg1.d1.s2| null| root.sg1| DOUBLE| GORILLA| LZ4| null| null| null| null| BASE|
|root.factory.device_monitor.total_runtime| null|root.factory| INT64|TS_2DIFF| LZ4| null| null| null| null| BASE|
| root.factory.device_monitor.temperature| null|root.factory| FLOAT| GORILLA| LZ4| null| null| null| null| BASE|
| root.factory.device_monitor.humidity| null|root.factory| DOUBLE| GORILLA| LZ4| null| null| null| null| BASE|
| root.factory.device_monitor.firmware_bin| null|root.factory| BLOB| PLAIN| LZ4| null| null| null| null| BASE|
| root.factory.device_monitor.deploy_time| null|root.factory|TIMESTAMP|TS_2DIFF| LZ4| null| null| null| null| BASE|
| root.factory.device_monitor.alarm_flag| null|root.factory| BOOLEAN| RLE| LZ4| null| null| null| null| BASE|
| root.factory.device_monitor.firmware| null|root.factory| TEXT| PLAIN| LZ4| null| null| null| null| BASE|
| root.factory.device_monitor.rpm| null|root.factory| INT32|TS_2DIFF| LZ4| null| null| null| null| BASE|
| root.factory.device_monitor.report_date| null|root.factory| DATE|TS_2DIFF| LZ4| null| null| null| null| BASE|
+-----------------------------------------+-----+------------+---------+--------+-----------+-------------------------+--------------+--------+------------------+--------+
Total line number = 14
It costs 0.009s
SHOW TIMESERIES root.factory.**; -- 指定前缀
SHOW TIMESERIES root.factory.** WHERE DATATYPE=FLOAT; -- 按类型过滤
SHOW TIMESERIES root.factory.** WHERE TIMESERIES contains 'wt01';
IoTDB> SHOW TIMESERIES root.factory.** WHERE TIMESERIES contains 'wt01';
+----------------------------------+-----+------------+--------+--------+-----------+----+----------+--------+------------------+--------+
| Timeseries|Alias| Database|DataType|Encoding|Compression|Tags|Attributes|Deadband|DeadbandParameters|ViewType|
+----------------------------------+-----+------------+--------+--------+-----------+----+----------+--------+------------------+--------+
|root.factory.wf01.wt01.temperature| null|root.factory| FLOAT| RLE| LZ4|null| null| null| null| BASE|
| root.factory.wf01.wt01.status| null|root.factory| BOOLEAN| PLAIN| LZ4|null| null| null| null| BASE|
+----------------------------------+-----+------------+--------+--------+-----------+----+----------+--------+------------------+--------+
Total line number = 2
It costs 0.008s
SHOW TIMESERIES root.factory.** LIMIT 10 OFFSET 10;
SHOW LATEST TIMESERIES; -- 只看最后写入的
统计-测点数量
-- 统计测点数量
COUNT TIMESERIES root.**;
IoTDB> COUNT TIMESERIES root.**;
+-----------------+
|count(timeseries)|
+-----------------+
| 13|
+-----------------+
Total line number = 1
It costs 0.007s
COUNT TIMESERIES root.factory.** GROUP BY LEVEL=2; -- 按层级聚合统计
IoTDB> COUNT TIMESERIES root.factory.** GROUP BY LEVEL=2; -- 按层级聚合统计
+---------------------------+-----------------+
| Column|count(timeseries)|
+---------------------------+-----------------+
|root.factory.device_monitor| 9|
| root.factory.wf01| 4|
+---------------------------+-----------------+
Total line number = 2
It costs 0.010s
Msg: org.apache.iotdb.jdbc.IoTDBSQLException: 700: Error occurred while parsing SQL to physical plan: line 1:0 mismatched input '-' expecting {ALTER, CALL, CLEAR, COUNT, CREATE, DEACTIVATE, DEBUG, DELETE, DROP, EXPLAIN, EXTEND, FLUSH, GRANT, INSERT, KILL
, LIST, LOAD, MIGRATE, RECONSTRUCT, REMOVE, REVOKE, SELECT, SET, SETTLE, SHOW, START, STOP, UNLOAD, UNSET, VERIFY, REPAIR}
IoTDB>
删除-测点
DELETE TIMESERIES root.factory.wf01.wt01.status;
DELETE TIMESERIES root.factory.wf02.*;
写入数据
-- 单列写入
INSERT INTO root.factory.wf02.wt02(timestamp, status) VALUES(1, true);
-- 多列同时间点
INSERT INTO root.factory.wf02.wt02(timestamp, status, hardware) VALUES(2, false, 'v2');
-- 多行(多列)批量
INSERT INTO root.factory.wf02.wt02(timestamp, status, hardware) VALUES(3, false, 'v3'), (4, true, 'v4');
-- 用服务器当前时间戳(省略 timestamp 列)
INSERT INTO root.factory.wf02.wt02(status, hardware) VALUES(false, 'v2');
-- 时间对齐序列写入(要加 ALIGNED 关键字)
INSERT INTO root.sg1.d1(time, s1, s2) ALIGNED VALUES(1, 1, 1);
查询数据
-- 单测点时间范围查询
SELECT temperature FROM root.factory.wf01.wt01 WHERE time < 2099-11-01T00:08:00.000;
-- 多测点
SELECT status, temperature FROM root.factory.wf01.wt01 WHERE time > 2017-11-01T00:05:00.000 AND time < 2099-11-01T00:12:00.000;
-- 通配符查某设备下全部
IoTDB> SELECT * FROM root.factory.wf02.wt02;
+-----------------------------+-------------------------------+-----------------------------+
| Time|root.factory.wf02.wt02.hardware|root.factory.wf02.wt02.status|
+-----------------------------+-------------------------------+-----------------------------+
|1970-01-01T08:00:00.001+08:00| null| true|
|1970-01-01T08:00:00.002+08:00| v2| false|
|1970-01-01T08:00:00.003+08:00| v3| false|
|1970-01-01T08:00:00.004+08:00| v4| true|
|2026-10-12T16:39:53.096+08:00| v2| false|
+-----------------------------+-------------------------------+-----------------------------+
Total line number = 5
It costs 0.057s
IoTDB> SELECT * FROM root.factory.wf02.*;
+-----------------------------+-------------------------------+-----------------------------+
| Time|root.factory.wf02.wt02.hardware|root.factory.wf02.wt02.status|
+-----------------------------+-------------------------------+-----------------------------+
|1970-01-01T08:00:00.001+08:00| null| true|
|1970-01-01T08:00:00.002+08:00| v2| false|
|1970-01-01T08:00:00.003+08:00| v3| false|
|1970-01-01T08:00:00.004+08:00| v4| true|
|2026-10-12T16:39:53.096+08:00| v2| false|
+-----------------------------+-------------------------------+-----------------------------+
Total line number = 5
It costs 0.013s
-- 查最新一个点
IoTDB> SELECT LAST status FROM root.factory.wf02.wt02;
+-----------------------------+-----------------------------+-----+--------+
| Time| Timeseries|Value|DataType|
+-----------------------------+-----------------------------+-----+--------+
|2026-10-12T16:39:53.096+08:00|root.factory.wf02.wt02.status|false| BOOLEAN|
+-----------------------------+-----------------------------+-----+--------+
Total line number = 1
It costs 0.017s
-- 查最新多个点
IoTDB> SELECT LAST status,hardware FROM root.factory.wf02.wt02;
+-----------------------------+-------------------------------+-----+--------+
| Time| Timeseries|Value|DataType|
+-----------------------------+-------------------------------+-----+--------+
|2026-10-12T16:39:53.096+08:00| root.factory.wf02.wt02.status|false| BOOLEAN|
|2026-10-12T16:39:53.096+08:00|root.factory.wf02.wt02.hardware| v2| TEXT|
+-----------------------------+-------------------------------+-----+--------+
Total line number = 2
It costs 0.007s
IoTDB> SELECT LAST * FROM root.factory.wf02.wt02 ORDER BY TIMESERIES DESC;
+-----------------------------+-------------------------------+-----+--------+
| Time| Timeseries|Value|DataType|
+-----------------------------+-------------------------------+-----+--------+
|2026-10-12T16:39:53.096+08:00| root.factory.wf02.wt02.status|false| BOOLEAN|
|2026-10-12T16:39:53.096+08:00|root.factory.wf02.wt02.hardware| v2| TEXT|
+-----------------------------+-------------------------------+-----+--------+
Total line number = 2
It costs 0.014s
-- 降序 + 分页
SELECT * FROM root.factory.** WHERE time > 1 ORDER BY TIME DESC LIMIT 10;
-- 别名
IoTDB> SELECT s1 AS temperature, s2 AS speed,status FROM root.factory.wf02.wt02;
+-----------------------------+-----------------------------+
| Time|root.factory.wf02.wt02.status|
+-----------------------------+-----------------------------+
|1970-01-01T08:00:00.001+08:00| true|
|1970-01-01T08:00:00.002+08:00| false|
|1970-01-01T08:00:00.003+08:00| false|
|1970-01-01T08:00:00.004+08:00| true|
|2026-10-12T16:39:53.096+08:00| false|
+-----------------------------+-----------------------------+
Total line number = 5
It costs 0.011s
删除数据
-- 按时间范围删
DELETE FROM root.ln.wf02.wt02.status
WHERE time >= 2017-01-01T00:00:00
AND time <= 2017-11-01T16:26:00;
-- 删某测点全部数据
DELETE FROM root.ln.wf02.wt02.status;
注意:DELETE 的 WHERE 只允许
time > XXX/time <= XXX这种原子条件,两个之间用 AND 连接,不支持OR。
常见操作-Table管理 (表模型)
- 推荐:本文档
CASE 以一张「设备工况表」为例 (表模型版) | 表模型模式下的使用示范(V2)
常见操作-TTL管理 (数据自动清理周期)
- TTL 的设置层级取决于 IoTDB 的数据模型:IoTDB 2.x 起分 树模型(Tree Model,传统模型) 和 表模型(Table Model),两者 TTL 粒度不同,都不止 database 一级。
树模型:库级 + 设备级(pathPattern 规则匹配)
- 查看TTL
SHOW TTL ON root.ods_xxx.ods_vhr_vehicle_can_sensors_timeseries;
- 调大TTL
SET TTL TO root.ods_xxx.ods_vhr_vehicle_can_sensors_timeseries 259200000000; -- 3000d
86400000 (毫秒级) -- 1d
2592000000 (毫秒级) -- 30d
259200000000 (毫秒级) -- 300d
946080000000 (毫秒级) -- 365d
- 官方定位是 设备级 TTL(device level),
set ttl to pathPattern的 path 是设备匹配前缀路径,而不是单条时序:
| 设置对象 | 写法示例 | 说明 |
|---|---|---|
| 数据库(旧语法兼容) | SET TTL TO root.sg 3600000; |
命中 database 时自动展开为 root.sg.**,对库下所有设备生效 |
| 库前缀批量 | SET TTL TO root.sg.group1.** 3600000; |
匹配该前缀下所有设备 |
| 单个具体设备 | SET TTL TO root.sg.group1.device001 3600000; |
路径不含通配符即视为具体设备;不校验设备元数据是否存在,可对未创建的设备预置规则 |
优先级规则:一个设备命中【多条规则】时,路径更精确(更长)的规则优先;同级内取更长(更宽松)的 TTL。例如 root.bj.hd.dist001.turbine001 > root.bj.hd.dist001.** > root.bj.hd.**。
关键限制:
- 不能精确到单条测点时序(如
root.sg.d1.s1不被支持作为 TTL 挂载点),设备下所有时序共用该设备 TTL。 - 全局最多 1000 条 TTL 规则,超限需先
UNSET TTL释放。 - TTL 按数据点时间戳判定过期,不是写入时间;过期数据查询/写入先被拦截,物理删除延迟到 Compaction 阶段。
- 查看:
SHOW ALL TTL、SHOW TTL ON root.sg.**、SHOW DEVICES(含每设备 TTL 列,INF表示无限保留)。
表模型:库级 + 表级(继承关系)
- 表模型 TTL 粒度是 表(Table),database 级只是新建表的默认值:
| 设置对象 | 写法示例 | 生效范围 |
|---|---|---|
| 数据库 | CREATE DATABASE db WITH (TTL=3600000); |
仅作为后续新建表的默认值,不追溯已存在的表 |
| 建表时指定 | CREATE TABLE t (...) WITH (TTL=3600); |
表级优先于库级 |
| 改已有表 | ALTER TABLE t SET PROPERTIES TTL=3600; |
表独立 TTL |
| 回退继承库级 | ALTER TABLE t SET PROPERTIES TTL=DEFAULT; |
跟随库 TTL |
| 取消表 TTL | ALTER TABLE t SET PROPERTIES TTL='INF'; |
表永久保留 |
重要限制:表模型目前不支持修改已建数据库的 TTL,库级 TTL 只能在建库语句 WITH (TTL=...) 中一次性指定;取消有效期只能把表 TTL 改为 INF。
对照速查
| 维度 | 树模型 Tree | 表模型 Table |
|---|---|---|
| 最小 TTL 粒度 | 设备(device,路径前缀) | 表(table) |
| 库级语义 | 库下全部设备(自动展开 .**) |
仅新建表默认值,不追溯旧表 |
| 多级覆盖 | 长前缀规则优先于短前缀 | 表级优先于库级,DEFAULT 回继承 |
| 库 TTL 可否后改 | 可以(SET/UNSET TTL 直接作用于库路径) |
不支持,只能建库时指定 |
| 规则数量上限 | 1000 条规则 | 按表/库独立配置,无统一规则上限说明 |
| 查看命令 | SHOW ALL TTL |
SHOW DATABASES / SHOW TABLES |
落地建议(结合车联网时序场景)
- 如果用树模型 + 设备模板想做"同一车型不同设备差异化保留"(如 OBD 高频数据 7 天、胎压数据 90 天),应在设备路径段上规划前缀(
root.car.obd.**、root.car.tpms.**)再挂 TTL,而不是指望测点级 TTL。 - 如果需要整表差异化保留且建库后可调,用表模型的表级
ALTER TABLE ... SET PROPERTIES TTL;但库级 TTL 务必在CREATE DATABASE时就定好,后期无法补设。 - 树模型降低/取消 TTL 后,原本因 TTL 不可见的历史数据可能重新可见,上线前先在测试库验证过期数据的查询行为。
2 进阶用法
连续查询特性(Continuous Query,CQ)
- Apache IoTDB 的连续查询(Continuous Query,CQ)是一种面向时序数据的"【滚动窗口 + 增量执行】"的【持续聚合机制】
本质类似定时【物化视图】:注册一条聚合查询后,系统按固定周期对新到达的数据反复执行,并把结果写入目标时序,供下游持续消费。
核心机制
- 滚动窗口:每个执行周期只处理上次执行后新进入的数据,窗口随时间滑动,保证不重不漏。
- 三个时间要素:
- 定义查询的聚合窗口长度(
FOR指定统计跨度); - 执行频率(
RESAMPLE EVERY,即多久滑动一次窗口); - 加上"上次执行时间"记录,新窗口从该时间点起算,避免数据遗漏。
- 定义查询的聚合窗口长度(
- 结果落库:聚合结果写入指定目标时序,天然形成一条"降采样/汇总"的持续更新序列,下游可按需读取。
关键语法结构
CREATE CONTINUOUS QUERY cq_1
RESAMPLE EVERY 5s FOR 1m -- 每 5s 执行一次,每次聚合最近 1 分钟窗口
BEGIN
SELECT avg(temperature)
INTO root.sensor.cq.avg_temp
FROM root.sensor.raw
GROUP BY time(1m) -- 窗口按 1 分钟分桶
END
要点:
EVERY(执行频率)不能低于配置项continuous_query_min_every_interval,防止 CQ 过密耗尽资源。- 可省略
FOR/EVERY,此时每次执行取全量历史做一次性聚合(非增量),需注意数据量。 GROUP BY TIME负责窗口分桶,是 CQ 与普通查询在语义上的分界。
与普通 GROUP BY 的区别
| 维度 | 普通 GROUP BY | 连续查询 CQ |
|---|---|---|
| 执行方式 | 一次性离线查询 | 周期性持续执行 |
| 数据范围 | 全量时间范围 | 增量(自上次执行起的新数据) |
| 结果去向 | 返回给客户端 | 写入目标时序(持续更新) |
| 适用场景 | 历史报表、离线分析 | 实时指标、持续监控、降采样 |
相关配置(iotdb-common.properties)
continuous_query_submit_thread:提交 CQ 的线程数continuous_query_execution_thread:执行 CQ 的线程数continuous_query_max_pending_events:待执行事件队列上限continuous_query_min_every_interval:最小执行间隔(安全阀)
对车联网时序场景的适用性
结合可能落地 IoTDB 2.0.11 的车辆数据场景,CQ 很适合做【实时车辆】指标的持续聚合,例如:
- 车辆实时状态(速度/里程)按分钟/小时滚动求均值写入汇总序列;
- 告警类统计(超速次数、急刹频次)持续更新供下游实时消费;
- 降采样:高频原始数据 → 分钟级/小时级汇总,减少下游查询压力。
需要注意:CQ 是追加/更新目标序列而非【替换】,设计目标序列层级(原始层 → 汇总层)时需与树模型/TTL 策略统一规划。
IoTDB 2.0.11 Topic 实时订阅:尚未开放
- 结论:没错,Apache IoTDB 2.0.11 确实尚未开放 实时订阅特性;且存在版本差别。
源代码情况:确实关闭了
- 我让AI把开源代码翻了个底朝天,证据如下:
开源 2.0.11 里,订阅功能的总开关被硬编码关闭了
在 v2.0.11 源码的 CommonConfig.java 第 61 行,写死着:
public static final boolean SUBSCRIPTION_ENABLED = false;
getSubscriptionEnabled()直接返回这个常量,不读任何 properties 配置——所以改iotdb-common.properties没用,这是编译期写死的。其他订阅调优参数(内存占比、线程数等)都是可配置的,唯独这个总开关不行。- 精确到你的报错:
iotdb-server-2.0.11.jar里的SubscriptionReceiverAgent收到订阅请求时检查这个开关,为 false 就抛出 1912Subscription is not enabled。- 还查了 master 主线,依然是
false,社区还没有打开它。
- 而 1.3.x 开源版没有这个开关
拉了 v1.3.4 的 CommonConfig.java 对比——里面根本没有
SUBSCRIPTION_ENABLED这个常量,【订阅开箱即用】。
为什么 2.x 要关掉?
2025 年起 IoTDB 重构为 【Tree/Table】(设备路径/表)双模型,【订阅代码】也整个重构成了 tree/table 两套 API(我们在编译你项目时验证过:2.0.11 的 jar 里类名全变了)。
重构未完全收尾,官方就把【总闸】放下,等【代码完全就绪】再放开。订阅的代码是开源的、就在 jar 包里——只是开源 release 编译时把入口关了。
现状对照
| 方案 | 现状 |
|---|---|
| 开源 2.0.11 + Topic 订阅 | 不可行(开关写死 false) |
| 开源 1.3.x + Topic 订阅 | 完全可用 |
| 天谋商业版 2.x | 开关打开 |
| Flink 1.20 + 1.3.4 客户端 API | 客户端兼容,可用 |
Apache iotDB 2.x 的实时订阅特性,预计可能啥时候会开放出来?官方又是咋说的?相关Issue的情况?
2026.11.03
- 开放时间:无时间表、无 roadmap 承诺、master 开关未动—— 目前没有任何证据指向近期会打开 ,而且只要没人提交打开这个常量的 PR,它就永远关着。
- 整个 2.0 系列(2.0.0 一路到 2.0.11 和后续 patch)发布至今,这个闸一次都没打开过——也就是说它已经关了一年多,跨了十几个 release;
- 官方依旧没有任何 roadmap 承诺。
-
但技术方向是明确的:功能代码完全开源且在活跃维护,商业版同源可用,开源开放大概率只是“待重构收尾后的一个 release 决定”,而不是【计划移除】的能力。因此 不建议为它改架构,但也不必否定这条路线 。
-
等开放的话,盯两个信号即可:
CommonConfig.java里SUBSCRIPTION_ENABLED常量的变更,以及新 2.x 版本的 Release Notes;想更快要准信就上 GitHub 提 issue 问 DataNode 团队。 -
我让AI帮我推测一下可能开放的时间:
- 未来 3~6 个月(到 2027 春):低,AI自己的评估: 20~30%;
- 2027 年内:中等,40~60%;
- 也存在真实可能:他们憋到下一个大版本(3.x)随重构收尾一起放开,那就得按 1~2 年来等。
理由是——闸已经【关了一年多、还纹丝不动】,说明官方并不急于在 2.x 里兑现它。
- 【
1912: Subscription is not enabled/ 开源 2.x 订阅何时开】 的相近 Issue / PR 清单
[Feature Request] 咨询:开源发行版中数据订阅(SUBSCRIPTION_ENABLED)的启用时间安排 - Github/Apache IotDB
| 编号 | 标题 | 状态 / 时间 | 相近点与关键内容 |
|---|---|---|---|
| #17923 | [Bug] 已配置 enable_mqtt_service=true,创建 Topic 时仍提示 Subscription is not enabled | Issue,已关闭;2026-06-12 提出,06-17 关闭 | 与你情况几乎完全相同的报告:2.0.8 单机、CREATE TOPIC 报一模一样的 1912 错误。维护者 CritasWang 答复「订阅功能暂时还未全面放开,还在优化当中」;HTHou 补充「计划等功能完善后再放开入口」——这是目前唯一找到的、官方对“何时开放”的公开回应,只给了方向(功能完善后放开),没给日期 |
| #18716 | [Test] Improve subscription client and disabled-mode coverage | PR,开放中;2026-09-24 | 新增 IoTDBSubscriptionDisabledIT 集成测试,专门验证关闭态下 Topic/订阅语句返回 SUBSCRIPTION_NOT_ENABLED_ERROR——说明「默认关闭」是被当作正式状态来测试和维护的,不是临时的意外 |
| #18457 | [Subscription] Disable subscription by default | PR,已合并;2026-08-12 | 「默认关闭订阅」本身的改造 PR,证实默认关闭是社区主动决策 |
| #18465 | [Subscription] Skip runtime when subscription is disabled | PR,已关闭;2026-08-13 | 关闭态下直接跳过订阅运行时,避免空转 |
| #18564 | [Subscription] Suppress pull commit progress error when subscription is disabled | PR,已关闭;2026-09-01 | 关闭态下抑制 pull commit 报错——用户侧误触发订阅 API 时的静默处理 |
| #18615 | [Subscription] Suppress expected commit progress warnings | PR,已关闭;2026-09-10 | 同类:抑制预期内的 commit progress 警告噪音 |
| #19019 | Support progress retention for initial and snapshot subscription topics | PR,已关闭;2026-10-26(9 条评论) | 订阅功能本身仍在活跃开发:保留初始/快照 Topic 的消费进度,属于开放前的收尾打磨 |
| #19037 | Reuse clusters in metadata, pipe, load, subscription and write integration tests | PR,开放中;2026-10-28 | 把订阅纳入共享集群集成测试体系,仍在完善测试基建 |
另有此前搜到的 #19053([Bugfix] Disable Subscription and Pipes containing data insertion under Ratis,开放中)——方向相反:还在扩大暂禁场景,进一步印证 2.x 线内订阅未到开放状态。
解决方法 & 临时出路(必读)
- 改用开源 1.3.4 服务端:订阅、Topic 立即可用,客户端依赖换成
iotdb-session:1.3.4,代码回到最初那版 API 就行,Flink 1.20 完全兼容。
短期最稳 : 测试项目走 1.3.x 开源 + 原生订阅 (1.3.4 的
iotdb-sessionjar 里实测含SubscriptionSession/SubscriptionPullConsumer/SubscriptionSessionDataSet三件套;官方文档也从 1.3.3 起就记录了这套功能。
-
留在 2.0.11,放弃【订阅】改用【轮询】 Source:写一个按高水位时间戳周期性
Session.executeQuery增量拉取的自定义 Source,秒级准实时,不需要任何配置改动。 -
自己改【源码】把常量改成 true 重编 2.0.11:不推荐,功能还在【重构期】,行为不可控且无官方支持。
-
将流式的时序数据推送到 kafka 等消息队列,再由 Flink 消费消息队列的数据。(直到 Apache IotDB 2.x 的实时订阅特性再次开放):推荐。
必须留在 2.0.11 的话 :写一个 增量拉取型 IoTDB Source(周期
executeQuery按 timestamp 高水位拉新数据 + checkpoint 存水位)替代订阅 Source,秒级准实时,不依赖任何开关,官方全支持。
3 案例实践
CASE 以一张「设备工况表」为例 (树模型版)
- 以一张「设备工况表」为例,覆盖表模型全部 Field 类型,并给出建表、插入、查询的完整 SQL。
1. 建库、建表(含全类型 FIELD)
- 创建、并切换到指定数据库
CREATE DATABASE root.factory; -- DELETE DATABASE root.factory; -- 树模型
-- 若已存在时,将创建失败
show databases;
- 创建表
在已有库
root.factory下,每个物理量建一条时间序列,设备维度和工厂号通过TAGS挂为元数据:
CREATE TIMESERIES root.factory.device_monitor.temperature WITH DATATYPE=FLOAT;
CREATE TIMESERIES root.factory.device_monitor.humidity WITH DATATYPE=DOUBLE;
CREATE TIMESERIES root.factory.device_monitor.rpm WITH DATATYPE=INT32;
CREATE TIMESERIES root.factory.device_monitor.total_runtime WITH DATATYPE=INT64;
CREATE TIMESERIES root.factory.device_monitor.alarm_flag WITH DATATYPE=BOOLEAN;
CREATE TIMESERIES root.factory.device_monitor.firmware WITH DATATYPE=TEXT;
CREATE TIMESERIES root.factory.device_monitor.report_date WITH DATATYPE=DATE;
CREATE TIMESERIES root.factory.device_monitor.deploy_time WITH DATATYPE=TIMESTAMP;
CREATE TIMESERIES root.factory.device_monitor.firmware_bin WITH DATATYPE=BLOB;
-- 创建【带标签/属性】的测点:
CREATE TIMESERIES root.factory.device_monitor.pressure WITH DATATYPE=FLOAT, ENCODING=RLE, COMPRESSOR=SNAPPY TAGS(device_id=v1, tag2=v2) ATTRIBUTES(attr1=v1);
-- 设备 device_001
CREATE TIMESERIES root.factory.device_001.temperature
WITH DATATYPE=FLOAT, ENCODING=RLE, COMPRESSOR=SNAPPY
TAGS(device_id='device_001', location='chengdu');
CREATE TIMESERIES root.factory.device_001.rpm
WITH DATATYPE=INT32, ENCODING=RLE, COMPRESSOR=SNAPPY
TAGS(device_id='device_001', location='chengdu');
-- 设备 device_002
CREATE TIMESERIES root.factory.device_002.temperature
WITH DATATYPE=FLOAT, ENCODING=RLE, COMPRESSOR=SNAPPY
TAGS(device_id='device_002', location='beijing');
CREATE TIMESERIES root.factory.device_002.rpm
WITH DATATYPE=INT32, ENCODING=RLE, COMPRESSOR=SNAPPY
TAGS(device_id='device_002', location='beijing');
- 查看测点(指定前缀)
IoTDB> SHOW TIMESERIES root.factory.**; -- 查看测点(指定前缀)
+-----------------------------------------+-----+------------+---------+--------+-----------+----+----------+--------+------------------+--------+
| Timeseries|Alias| Database| DataType|Encoding|Compression|Tags|Attributes|Deadband|DeadbandParameters|ViewType|
+-----------------------------------------+-----+------------+---------+--------+-----------+----+----------+--------+------------------+--------+
|root.factory.device_monitor.total_runtime| null|root.factory| INT64|TS_2DIFF| LZ4|null| null| null| null| BASE|
| root.factory.device_monitor.temperature| null|root.factory| FLOAT| GORILLA| LZ4|null| null| null| null| BASE|
| root.factory.device_monitor.humidity| null|root.factory| DOUBLE| GORILLA| LZ4|null| null| null| null| BASE|
| root.factory.device_monitor.firmware_bin| null|root.factory| BLOB| PLAIN| LZ4|null| null| null| null| BASE|
| root.factory.device_monitor.deploy_time| null|root.factory|TIMESTAMP|TS_2DIFF| LZ4|null| null| null| null| BASE|
| root.factory.device_monitor.alarm_flag| null|root.factory| BOOLEAN| RLE| LZ4|null| null| null| null| BASE|
| root.factory.device_monitor.firmware| null|root.factory| TEXT| PLAIN| LZ4|null| null| null| null| BASE|
| root.factory.device_monitor.rpm| null|root.factory| INT32|TS_2DIFF| LZ4|null| null| null| null| BASE|
| root.factory.device_monitor.report_date| null|root.factory| DATE|TS_2DIFF| LZ4|null| null| null| null| BASE|
+-----------------------------------------+-----+------------+---------+--------+-----------+----+----------+--------+------------------+--------+
Total line number = 9
It costs 0.005s
Msg: org.apache.iotdb.jdbc.IoTDBSQLException: 700: Error occurred while parsing SQL to physical plan: line 1:0 mismatched input '-' expecting {ALTER, CALL, CLEAR, COUNT, CREATE, DEACTIVATE, DEBUG, DELETE, DROP, EXPLAIN, EXTEND, FLU
SH, GRANT, INSERT, KILL, LIST, LOAD, MIGRATE, RECONSTRUCT, REMOVE, REVOKE, SELECT, SET, SETTLE, SHOW, START, STOP, UNLOAD, UNSET, VERIFY, REPAIR}
2. 插入数据
INSERT INTO root.factory.device_monitor(timestamp, temperature, rpm) VALUES (now(), 23.5, 1200);
-- root.factory.device_001/device_002 的模型
-- 单行插入(多测点同行)
INSERT INTO root.factory.device_001(timestamp, temperature, rpm) VALUES (2026-10-01T08:00:00.000, 36.5, 1200);
-- 批量多行插入
INSERT INTO root.factory.device_001(timestamp, temperature, rpm)
VALUES (2026-10-01T08:00:00.000, 36.5, 1200),
(2026-10-01T09:00:00.000, 37.2, 1500),
(2026-10-05T12:00:00.000, 38.0, 1350);
INSERT INTO root.factory.device_002(timestamp, temperature, rpm)
VALUES (2026-10-02T08:00:00.000, 22.4, 900),
(2026-10-06T18:30:00.000, 23.1, 1100),
(2026-10-10T10:00:00.000, 24.0, 980);
-- 只插单个测点
INSERT INTO root.monitor.device_001(timestamp, temperature)
VALUES (2026-10-08T16:00:00.000, 36.9);
- 查验
SELECT * FROM root.factory.**;
IoTDB> SELECT * FROM root.factory.device_001
+-----------------------------+-----------------------------------+---------------------------+
| Time|root.factory.device_001.temperature|root.factory.device_001.rpm|
+-----------------------------+-----------------------------------+---------------------------+
|2026-10-01T08:00:00.000+08:00| 36.5| 1200|
|2026-10-01T09:00:00.000+08:00| 37.2| 1500|
|2026-10-05T12:00:00.000+08:00| 38.0| 1350|
+-----------------------------+-----------------------------------+---------------------------+
Total line number = 3
It costs 0.011s
IoTDB> SELECT * FROM root.factory.device_002
+-----------------------------+-----------------------------------+---------------------------+
| Time|root.factory.device_002.temperature|root.factory.device_002.rpm|
+-----------------------------+-----------------------------------+---------------------------+
|2026-10-02T08:00:00.000+08:00| 22.4| 900|
|2026-10-06T18:30:00.000+08:00| 23.1| 1100|
|2026-10-10T10:00:00.000+08:00| 24.0| 980|
+-----------------------------+-----------------------------------+---------------------------+
Total line number = 3
It costs 0.012s
IoTDB>
3. 查询示例(各类型用法)
- 过滤 + 排序
-- 按时间过滤
SELECT * FROM root.factory.device_monitor WHERE time > 2026-10-01
-- 日期过滤 + 排序
IoTDB> SELECT device_id, temperature FROM root.factory.device_0* WHERE time > 2026-10-01 ORDER BY time DESC;
+-----------------------------+-----------------------------------+-----------------------------------+
| Time|root.factory.device_002.temperature|root.factory.device_001.temperature|
+-----------------------------+-----------------------------------+-----------------------------------+
|2026-10-10T10:00:00.000+08:00| 24.0| null|
|2026-10-06T18:30:00.000+08:00| 23.1| null|
|2026-10-05T12:00:00.000+08:00| null| 38.0|
|2026-10-02T08:00:00.000+08:00| 22.4| null|
|2026-10-01T09:00:00.000+08:00| null| 37.2|
|2026-10-01T08:00:00.000+08:00| null| 36.5|
+-----------------------------+-----------------------------------+-----------------------------------+
Total line number = 6
It costs 0.013s
IoTDB>
-- WHERE 数值运算 + 布尔过滤 + 字符串匹配
IoTDB> SELECT * FROM root.factory.device_monitor;
IoTDB> SELECT * FROM root.factory.device_monitor where temperature > 20 or firmware LIKE '%v2.%' or alarm_flag = true;
+-----------------------------+-----------------------------------------+---------------------------------------+------------------------------------+----------------------------------------+---------------------------------------+--------------------------------------+------------------------------------+----------
---------------------+---------------------------------------+
| Time|root.factory.device_monitor.total_runtime|root.factory.device_monitor.temperature|root.factory.device_monitor.humidity|root.factory.device_monitor.firmware_bin|root.factory.device_monitor.deploy_time|root.factory.device_monitor.alarm_flag|root.factory.device_monitor.firmware|root.facto
ry.device_monitor.rpm|root.factory.device_monitor.report_date|
+-----------------------------+-----------------------------------------+---------------------------------------+------------------------------------+----------------------------------------+---------------------------------------+--------------------------------------+------------------------------------+----------
---------------------+---------------------------------------+
|2026-10-12T16:57:18.684+08:00| null| 23.5| null| null| null| null| null|
1200| null|
+-----------------------------+-----------------------------------------+---------------------------------------+------------------------------------+----------------------------------------+---------------------------------------+--------------------------------------+------------------------------------+----------
---------------------+---------------------------------------+
Total line number = 1
It costs 0.013s
- 聚合统计
-- 分组聚合统计(单个测点)
IoTDB> SELECT AVG(temperature) FROM root.factory.device_monitor WHERE time >= 2026-10-01T00:00:00 AND time < 2026-10-13T00:00:00;
+--------------------------------------------+
|AVG(root.factory.device_monitor.temperature)|
+--------------------------------------------+
| 23.5|
+--------------------------------------------+
Total line number = 1
It costs 0.007s
IoTDB> SELECT AVG(temperature) FROM root.factory.** WHERE time >= 2026-10-01T00:00:00 AND time < 2026-10-13T00:00:00 GROUP BY LEVEL = 2;
+----------------------------------+----------------------------------+--------------------------------------+
|AVG(root.*.device_002.temperature)|AVG(root.*.device_001.temperature)|AVG(root.*.device_monitor.temperature)|
+----------------------------------+----------------------------------+--------------------------------------+
| 23.166666666666668| 37.233333587646484| 23.5|
+----------------------------------+----------------------------------+--------------------------------------+
Total line number = 1
It costs 0.014s
-- 若设备用 tag 建模,用 `GROUP BY TAGS` 更贴近某些查询需求(按 device_id 分组)
IoTDB> SELECT AVG(temperature) FROM root.factory.** WHERE time >= 2026-10-01T00:00:00 AND time < 2026-10-13T00:00:00 GROUP BY TAGS(device_id);
+----------+------------------+
| device_id| avg(temperature)|
+----------+------------------+
|device_001|37.233333587646484|
|device_002|23.166666666666668|
| NULL| 23.5|
+----------+------------------+
Total line number = 3
It costs 0.021s
CASE 树模型的数据集可支持建 "树转表视图",用表语法查询
官方有《Tree-to-Table Mapping》章节的完整语法和示例。
下面提供可执行的完整闭环样例(树模型写入 → 建树转表视图 → 表语法查询 → 视图管理),以官方风机构例子为基底。
前提
- 该功能 V2.0.5 起支持;建视图语句只能在【表模型】下执行(
SET SQL_DIALECT = TABLE)。 - 视图只读,不能通过视图写入数据(数据仍走树模型写入)。
- 【视图列】只支持
TAG / FIELD / TIME,不支持【ATTRIBUTE】。
Step 1 树模型写入数据(树语法,可无模式自动建表)
SET SQL_DIALECT = TREE;
-- 树路径:root.db.风机组.风机号.测点
INSERT INTO root.db.g1.t1(time, voltage, current)
VALUES (2026-10-12 08:00:00, 380.0, 12.5),
(2026-10-12 08:05:00, 382.0, 12.8);
INSERT INTO root.db.g1.t2(time, voltage, current)
VALUES (2026-10-12 08:00:00, 399.0, 14.2);
INSERT INTO root.db.g2.t1(time, voltage, current)
VALUES (2026-10-12 08:00:00, 375.0, 11.9);
- 查验
IoTDB> select * from root.db.**;
+-----------------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
| Time|root.db.g1.t1.current|root.db.g1.t1.voltage|root.db.g1.t2.current|root.db.g1.t2.voltage|root.db.g2.t1.current|root.db.g2.t1.voltage|
+-----------------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
|2026-10-12T08:00:00.000+08:00| 12.5| 380.0| 14.2| 399.0| 11.9| 375.0|
|2026-10-12T08:05:00.000+08:00| 12.8| 382.0| null| null| null| null|
+-----------------------------+---------------------+---------------------+---------------------+---------------------+---------------------+---------------------+
Total line number = 2
It costs 0.015s
Step2 建树转【表视图】(客户端:必须切到【表模型】模式下)
SET SQL_DIALECT = TABLE;
-- 表模型下,数据库需要先显式创建:
CREATE DATABASE viewdb;
CREATE OR REPLACE VIEW viewdb.wind_turbine (
wind_turbine_group STRING TAG,
wind_turbine_number STRING TAG,
voltage DOUBLE FIELD,
current2 DOUBLE FIELD FROM current -- 把视图的 `current2` 列映射到树模型里的 `current1` 测点
)
WITH (ttl = 604800000) -- 可选,视图级 TTL,只影响查询可见性
AS root.db.**;
SHOW TABLES FROM viewdb;
-- DROP VIEW IF EXISTS viewdb.wind_turbine;
IoTDB> CREATE OR REPLACE VIEW viewdb.wind_turbine ( wind_turbine_group STRING TAG, wind_turbine_number STRING TAG, voltage DOUBLE FIELD, current2 DOUBLE FIELD FROM current ) WITH (ttl = 604800000) AS root.db.**;
Msg: The statement is executed successfully.
映射规则(官方明确):
AS root.db.**中最后一级必须是**,其他层级不能含*/**。- 从
root.db.之后开始,按顺序:第 1 级g1/g2→wind_turbine_group,第 2 级t1/t2→wind_turbine_number。 voltage/current两个FIELD列默认映射树模型【同名测点】,仅选中 DOUBLE 类型的时间序列。- 若树中【测点名】与【想要的列名】不同,用
FROM映射:current DOUBLE FIELD FROM current_new。
Step 3 用表语法查询同一份数据
-- 3.1 按标签 + 时间过滤
IoTDB> SELECT time, wind_turbine_group, wind_turbine_number, voltage FROM viewdb.wind_turbine WHERE wind_turbine_number = 't1' AND time >= 2026-10-12 00:00:00 ORDER BY time;
+-----------------------------+------------------+-------------------+-------+
| time|wind_turbine_group|wind_turbine_number|voltage|
+-----------------------------+------------------+-------------------+-------+
|2026-10-12T08:00:00.000+08:00| g1| t1| 380.0|
|2026-10-12T08:00:00.000+08:00| g2| t1| 375.0|
|2026-10-12T08:05:00.000+08:00| g1| t1| 382.0|
+-----------------------------+------------------+-------------------+-------+
Total line number = 3
It costs 0.041s
注:
time >= 2026-10-12T00:00:00中2026-10-12T00:00:00是【时间字面量】(裸写,不带引号),会被解析为 TIMESTAMP
-- 3.2 按标签分组 + 时间桶聚合
SELECT wind_turbine_group,
date_bin(1h, time) AS hour,
avg(voltage) AS avg_voltage,
max(current2) AS max_current
FROM viewdb.wind_turbine
WHERE time >= 2026-10-11 00:00:00
GROUP BY wind_turbine_group, date_bin(1h, time);
IoTDB> SELECT wind_turbine_group, date_bin(1h, time) AS hour, avg(voltage) AS avg_voltage, max(current2) AS max_current FROM viewdb.wind_turbine WHERE time >= 2026-10-11 00:00:00 GROUP BY wind_turbine_group, date_bin(1h, time);
+------------------+-----------------------------+-----------+-----------+
|wind_turbine_group| hour|avg_voltage|max_current|
+------------------+-----------------------------+-----------+-----------+
| g1|2026-10-12T08:00:00.000+08:00| 387.0| 14.2|
| g2|2026-10-12T08:00:00.000+08:00| 375.0| 11.9|
+------------------+-----------------------------+-----------+-----------+
Total line number = 2
It costs 0.056s
- 表模型时间分桶:
date_bin(间隔, time),【间隔写法】支持1s / 1m / 1h / 1d等。- 若希望缺失的时间桶也补行,用
date_bin_gapfill(1h, time)+FILL METHOD PREVIOUS。GROUP BY 1表示按 SELECT 第一个列分组,也可组合:GROUP BY 1, wind_turbine_group。
-- 3.3 跨设备关联(【表模型】独有的时序语义,树模型难实现)
SELECT a.time, a.wind_turbine_number, a.voltage, b.current2
FROM viewdb.wind_turbine a
ASOF JOIN viewdb.wind_turbine b
ON a.time <= b.time
WHERE a.wind_turbine_number = 't1';
IoTDB> SELECT a.time, a.wind_turbine_number, a.voltage, b.current2 FROM viewdb.wind_turbine a ASOF JOIN viewdb.wind_turbine b ON a.time <= b.time WHERE a.wind_turbine_number = 't1';
+-----------------------------+-------------------+-------+--------+
| time|wind_turbine_number|voltage|current2|
+-----------------------------+-------------------+-------+--------+
|2026-10-12T08:00:00.000+08:00| t1| 380.0| 12.5|
|2026-10-12T08:00:00.000+08:00| t1| 380.0| 14.2|
|2026-10-12T08:00:00.000+08:00| t1| 380.0| 11.9|
|2026-10-12T08:00:00.000+08:00| t1| 375.0| 12.5|
|2026-10-12T08:00:00.000+08:00| t1| 375.0| 14.2|
|2026-10-12T08:00:00.000+08:00| t1| 375.0| 11.9|
|2026-10-12T08:05:00.000+08:00| t1| 382.0| 12.8|
+-----------------------------+-------------------+-------+--------+
Total line number = 7
It costs 0.064s
Step 4 视图管理
SHOW TABLES DETAILS FROM viewdb; -- TableType 显示 VIEW FROM TREE
IoTDB> SHOW TABLES DETAILS FROM viewdb;
+------------+---------+------+-------+--------------+
| TableName| TTL(ms)|Status|Comment| TableType|
+------------+---------+------+-------+--------------+
|wind_turbine|604800000| USING| null|VIEW FROM TREE|
+------------+---------+------+-------+--------------+
Total line number = 1
It costs 0.002s
SHOW CREATE VIEW viewdb.wind_turbine; -- 查看完整定义(会补全默认值)
IoTDB> SHOW CREATE VIEW viewdb.wind_turbine;
+------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| View| Create View|
+------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
|wind_turbine|CREATE VIEW "wind_turbine" ("time" TIMESTAMP TIME,"wind_turbine_group" STRING TAG,"wind_turbine_number" STRING TAG,"voltage" DOUBLE FIELD,"current2" DOUBLE FIELD FROM "current") WITH (ttl=604800000) AS root."db".**|
+------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
Total line number = 1
It costs 0.003s
ALTER VIEW viewdb.wind_turbine ADD COLUMN temperature DOUBLE FIELD;
ALTER VIEW viewdb.wind_turbine SET PROPERTIES TTL = 86400000;
DROP VIEW IF EXISTS viewdb.wind_turbine;
对比:树模型转表视图 vs 原生的表模型
- 结论:原生表模型是"真正的表存储空间"——数据独立存进表模型的 TsFile,可写可改可治理;树转表视图只是一个"只读窗口/映射"——数据仍归属树模型,只是用表语法把它"看成表"来查询。 两者底层存储引擎相同(都落 TsFile),差异在数据归属、可写性与列能力。
| 对比维度 | 原生表模型 | 树转表视图 |
|---|---|---|
| 本质 | 真实存储,数据写入表模型空间 | 逻辑视图,数据仍在树模型 TsFile |
| 建表 | CREATE TABLE(定义 TIME/TAG/ATTRIBUTE/FIELD) |
CREATE VIEW ... AS 树路径,须先有表模型 database |
| 可写性 | 可写可更新:INSERT / UPDATE / DELETE / DELETE DEVICES | 只读,写入仍走树语法(树侧写、视图实时可见) |
| 列类别 | TIME / TAG / ATTRIBUTE / FIELD 全支持 | 仅 TIME / TAG / FIELD,不支持 ATTRIBUTE |
| 数据归属 | 表模型自己的 TsFile,独立存储 | 指向树模型 TsFile,实时映射 |
| 结构治理 | ALTER TABLE 加删列、改列类型(V2.0.8.2+)、TTL | ALTER VIEW 加删列(仅FIELD可删)、改名、TTL |
| 设备标识 | TAG 列组合 = 联合主键 | 树路径层级按顺序映射为 TAG 列 |
| 建模 | 需先定义 schema(可自动扩展列) | 无需建模,直接基于已有树结构 |
| 适用 | 全新场景、需要写入/更新、数据治理 | 复用存量树数据、免迁移、树写表查协同 |
- 怎么选
- 数据已在树模型、想做分析又不想迁移 → 树转表视图(零迁移,两种语法处理同一份数据)。
- 全新场景、要标准表语义、需要写/更新/删除、做数据治理 → 原生表模型。
- 注意:视图只读,不能替代需要写入的表;且视图列没有 ATTRIBUTE,属性类信息只能用原生表。
下图给出两者的数据归属与读写路径对比(示意):

关键约束速记
| 项 | 约束 |
|---|---|
| prefixPath | 最后一级必为 **,其余层级不可含通配符 |
| TAG 列 | 按顺序对应 prefixPath 之后每一级路径节点;树中设备层级 ≤ TAG 列数(加 RESTRICT 则要求恰好相等) |
| FIELD 列 | 默认映射同名测点,可用 FROM original_measurement 改名;一个测点只能映射一个 FIELD |
| 只读 | 视图不可写;树侧继续用树语法写入 |
| 重名 | 表与视图不可同名 |
| TTL | 视图 TTL 仅做 WHERE time > now()-TTL 过滤,不影响树模型物理删除 |
| 对齐差异 | 对齐设备下,全空行视图会保留(同表模型);非对齐设备下全空行不保留 |
若【树模型】只有测点、【无设备层级】(如站控 root.db.DCS_PIT_02105A 等),可建【"宽表"视图】(每个【测点】一列)或【"窄表"视图】(sensor_id STRING TAG, value DOUBLE FIELD),后者更适合【多测点同构场景】。
CASE 以一张「设备工况表」为例 (表模型版)
以一张「设备工况表」为例,覆盖表模型全部 Field 类型,并给出建表、插入、查询的完整 SQL。
- 推荐文献
- 表模型的基本概念
- 时间列(TIME) / 标签列(TAG) / 属性列(ATTRIBUTE) / 测量列(字段)
在查询过滤效率方面,一般优先顺序为:先按时间列和标签列,再按属性列,最后按测量列。
- 设备与测量点
在表模型中,设备通过表中所有TAG列的值组合来唯一标识。例如,如果一个表包含三个TAG列:region(区域)、plant_id(工厂编号)和device_id(设备编号),那么每个区域 + 工厂编号 + 设备编号的唯一组合就代表一个独立的设备。
测量点对应表格中的FIELD列。单个设备的每个FIELD列会随时间生成多个数据点,这些按时间顺序排列的数据点构成一个时间序列。
因此,表模型中每张表格的测量点数量可用以下公式表示: ** 每张表的【测量点数量】 = 【设备数量】 × 【现场列数量】 **
1. 建库、建表(含全类型 FIELD)
CREATE DATABASE factory; -- 先建数据库
USE factory;
-- DROP TABLE device_monitor;
CREATE TABLE device_monitor (
ts TIMESTAMP TIME, -- 时间列由 `ts TIMESTAMP` 承担;若表中存在多个 TIMESTAMP 列(如 `deploy_time`),写入时以 TIME 对应的 `ts` 为准。
device_id STRING TAG,
plant_code STRING TAG,
temperature FLOAT, -- 单精度浮点
humidity DOUBLE, -- 双精度浮点
rpm INT32, -- 32 位整数
total_runtime INT64, -- 64 位整数
alarm_flag BOOLEAN, -- 布尔
firmware STRING, -- 字符串
report_date DATE, -- 日期 | 列类型是 `DATE`,只接受 `'YYYY-MM-DD'` 字符串字面量
deploy_time TIMESTAMP FIELD, -- 时间戳
firmware_bin BLOB -- 二进制
);
- 列类别(TAG/ATTRIBUTE/TIME/FIELD)是可省略项,省略时默认为 【FIELD】(测点列)。
真正有区别的是列类别之间(你表中的列到底归哪类影响行为和语义):
| 类别 | 含义 | 关键特性 |
|---|---|---|
| FIELD(默认,你大部分列) | 测点,随时间变化的采集值 | 可用 UPDATE 更新、可 ALTER 删列、参与时序聚合(avg/max 等) |
| TAG(建议 device_id/plant_code) | 设备标识 | 联合主键,不可修改/删除,只能新增;仅 STRING;用于 WHERE/分组过滤 |
| ATTRIBUTE(可选) | 设备静态属性 | 不随时间变化,可更新 |
| TIME(ts) | 时间列 | 每表必须一个,类型必为 TIMESTAMP |
- 查验
IoTDB:factory> show databases;
+------------------+-------+-----------------------+---------------------+---------------------+
| Database|TTL(ms)|SchemaReplicationFactor|DataReplicationFactor|TimePartitionInterval|
+------------------+-------+-----------------------+---------------------+---------------------+
| factory| INF| 1| 1| 604800000|
|information_schema| INF| null| null| null|
+------------------+-------+-----------------------+---------------------+---------------------+
Total line number = 2
It costs 0.002s
IoTDB:factory> show create table device_monitor;
+--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------+
| Table|
Create Table|
+--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------+
|device_monitor|CREATE TABLE "device_monitor" ("ts" TIMESTAMP TIME,"device_id" STRING TAG,"plant_code" STRING TAG,"temperature" FLOAT FIELD,"humidity" DOUBLE FIELD,"rpm" INT32 FIELD,"total_runtime" INT64 FIELD,"alarm_flag" BOOLEAN FIELD,"firmware" STRING
FIELD,"report_date" DATE FIELD,"deploy_time" TIMESTAMP FIELD,"firmware_bin" BLOB FIELD) WITH (ttl='INF')|
+--------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------+
Total line number = 1
It costs 0.014s
IoTDB:factory>
2. 插入数据
-- 插入单条数据
INSERT INTO device_monitor (
device_id, plant_code, ts, temperature, humidity, rpm,
total_runtime, alarm_flag, firmware, report_date, deploy_time, firmware_bin
) VALUES (
'D001', 'P-A', '2026-10-12 08:00:00', 25.3, 62.5, 3000,
123456789, true, 'v2.1.0', '2026-10-12', '2026-10-12 07:00:00', X'DEADBEEF'
);
-- 批量插入多条数据
INSERT INTO device_monitor (
device_id, plant_code, ts, temperature, humidity, rpm,
total_runtime, alarm_flag, firmware, report_date, deploy_time, firmware_bin
) VALUES
('D001', 'P-A', '2026-10-12 08:00:00', 25.3, 62.5, 3000, 123456789, true, 'v2.1.0', '2026-10-12', '2026-10-12 07:00:00', X'DEADBEEF'),
('D001', 'P-A', '2026-10-12 08:05:00', 25.6, 62.3, 3010, 123456789, false, 'v2.1.0', '2026-10-12', '2026-10-12 07:00:00', X'DEADBEEF'),
('D001', 'P-A', '2026-10-12 08:10:00', 26.1, 62.0, 3040, 123456789, false, 'v2.1.0', '2026-10-12', '2026-10-12 07:00:00', X'DEADBEEF'),
('D002', 'P-B', '2026-10-12 08:00:00', 18.2, 45.1, 2400, 987654321, false, 'v1.9.2', '2026-10-12', '2026-10-12 07:30:00', X'00FF00'),
('D002', 'P-B', '2026-10-12 08:10:00', 19.0, 45.8, 2450, 987654321, true, 'v1.9.2', '2026-10-12', '2026-10-12 07:30:00', X'00FF00'),
('D003', 'P-A', '2026-10-12 08:00:00', 31.5, 70.0, 3550, 456123, true, 'v2.2.0', '2026-10-12', '2026-10-11 23:59:00', X'CAFEBABE'),
('D003', 'P-A', '2026-10-12 08:15:00', 31.8, 69.5, 3580, 456123, false, 'v2.2.0', '2026-10-12', '2026-10-11 23:59:00', X'CAFEBABE'),
('D004', 'P-C', '2026-10-12 08:00:00', 22.0, 55.0, 1800, 789012, false, 'v1.0.5', '2026-10-12', '2026-10-01 00:00:00', X'12345678');
- 说明:
- 时间值写法
2026-10-12 08:00:00(TIMESTAMP)、2026-10-12(DATE)。- BLOB 用十六进制字面量
X'DEADBEEF'或占位参数插入。- 时间戳精确到毫秒(TIME 列实际类型为 TIMESTAMP)。
3. 查询示例(各类型用法)
- 查询明细数据
IoTDB:factory> select * from device_monitor; -- 或 select * from factory.device_monitor
+-----------------------------+---------+----------+-----------+--------+----+-------------+----------+--------+-----------+-----------------------------+------------+
| ts|device_id|plant_code|temperature|humidity| rpm|total_runtime|alarm_flag|firmware|report_date| deploy_time|firmware_bin|
+-----------------------------+---------+----------+-----------+--------+----+-------------+----------+--------+-----------+-----------------------------+------------+
|2026-10-12T08:00:00.000+08:00| D002| P-B| 18.2| 45.1|2400| 987654321| false| v1.9.2| 2026-10-12|2026-10-12T07:30:00.000+08:00| 0x00ff00|
|2026-10-12T08:10:00.000+08:00| D002| P-B| 19.0| 45.8|2450| 987654321| true| v1.9.2| 2026-10-12|2026-10-12T07:30:00.000+08:00| 0x00ff00|
|2026-10-12T08:00:00.000+08:00| D001| P-A| 25.3| 62.5|3000| 123456789| true| v2.1.0| 2026-10-12|2026-10-12T07:00:00.000+08:00| 0xdeadbeef|
|2026-10-12T08:05:00.000+08:00| D001| P-A| 25.6| 62.3|3010| 123456789| false| v2.1.0| 2026-10-12|2026-10-12T07:00:00.000+08:00| 0xdeadbeef|
|2026-10-12T08:10:00.000+08:00| D001| P-A| 26.1| 62.0|3040| 123456789| false| v2.1.0| 2026-10-12|2026-10-12T07:00:00.000+08:00| 0xdeadbeef|
|2026-10-12T08:00:00.000+08:00| D003| P-A| 31.5| 70.0|3550| 456123| true| v2.2.0| 2026-10-12|2026-10-11T23:59:00.000+08:00| 0xcafebabe|
|2026-10-12T08:15:00.000+08:00| D003| P-A| 31.8| 69.5|3580| 456123| false| v2.2.0| 2026-10-12|2026-10-11T23:59:00.000+08:00| 0xcafebabe|
|2026-10-12T08:00:00.000+08:00| D004| P-C| 22.0| 55.0|1800| 789012| false| v1.0.5| 2026-10-12|2026-10-01T00:00:00.000+08:00| 0x12345678|
+-----------------------------+---------+----------+-----------+--------+----+-------------+----------+--------+-----------+-----------------------------+------------+
Total line number = 8
It costs 0.026s
- 其他
-- 按时间范围查物理量(FLOAT/DOUBLE 聚合)
-- avg_temp : FLOAT 聚合 、 max_rpm : INT32 聚合
SELECT
device_id,
AVG(temperature) AS avg_temp,
MAX(rpm) AS max_rpm
FROM device_monitor
WHERE ts >= 2026-10-01 AND ts < 2026-10-13
GROUP BY device_id;
IoTDB:factory> SELECT device_id, AVG(temperature) AS avg_temp, MAX(rpm) AS max_rpm FROM device_monitor WHERE ts >= 2026-10-01 AND ts < 2026-10-13 GROUP BY device_id;
+---------+------------------+-------+
|device_id| avg_temp|max_rpm|
+---------+------------------+-------+
| D001|25.666666666666668| 3040|
| D002|18.600000381469727| 2450|
| D003|31.649999618530273| 3580|
| D004| 22.0| 1800|
+---------+------------------+-------+
Total line number = 4
It costs 0.046s
-- 布尔过滤 + 字符串匹配
SELECT device_id, ts, alarm_flag, firmware
FROM device_monitor
WHERE alarm_flag = true
AND firmware LIKE '%v2.%';
IoTDB:factory> SELECT device_id, ts, alarm_flag, firmware FROM device_monitor WHERE alarm_flag = true AND firmware LIKE '%v2.%';
+---------+-----------------------------+----------+--------+
|device_id| ts|alarm_flag|firmware|
+---------+-----------------------------+----------+--------+
| D001|2026-10-12T08:00:00.000+08:00| true| v2.1.0|
| D003|2026-10-12T08:00:00.000+08:00| true| v2.2.0|
+---------+-----------------------------+----------+--------+
Total line number = 2
It costs 0.022s
4. 类型换算提示
FLOAT → DOUBLE:可用CAST(temperature AS DOUBLE)提升精度。DOUBLE → FLOAT:可能丢失精度,谨慎使用。INT32 → INT64:直接兼容。- 建表后 Field 列类型一般不可直接修改,建议先确认好类型再建表。
CASE 以一张「设备工况表」为例 (表模型版) | 表模型模式下的使用示范(V2)
- 围绕「设备工况表」的完整样例 SQL,可直接在 CLI 里执行。
0. 建模约定(表模型核心概念)
- 时间列 TIME:每表必须有 1 个,类型
TIMESTAMP;不写时系统自动加名为time的第一列(自定义列名需 V2.0.8+)。 - 标签列 TAG:设备联合主键(如区域、车间、设备编号),不可删除,查询优先索引。
- 属性列 ATTRIBUTE:静态描述(型号、厂商),可用
UPDATE/INSERT更新。 - 测点列 FIELD:随时间变化的采集值,只能追加/覆盖,不能修改历史(重复时间戳写入即覆盖)。
- 库名/表名大小写不敏感、统一存小写;中文或特殊字符名须用双引号括起来。Windows CMD 不支持多行粘贴,长 SQL 需压成单行。
以下统一用库
factory、表device_condition(设备工况表)演示。
1. 数据库 DDL
-- 创建(可带属性:TTL 单位 ms、时间分区间隔、RegionGroup 数)
CREATE DATABASE IF NOT EXISTS factory WITH (TTL=31536000000);
-- 使用 / 查看
USE factory;
SHOW CURRENT_DATABASE;
IoTDB:factory> SHOW DATABASES;
+------------------+-------+-----------------------+---------------------+---------------------+
| Database|TTL(ms)|SchemaReplicationFactor|DataReplicationFactor|TimePartitionInterval|
+------------------+-------+-----------------------+---------------------+---------------------+
| factory| INF| 1| 1| 604800000|
|information_schema| INF| null| null| null|
| viewdb| INF| 1| 1| 604800000|
+------------------+-------+-----------------------+---------------------+---------------------+
Total line number = 3
It costs 0.002s
IoTDB:factory> SHOW DATABASES DETAILS;
+------------------+-------+-----------------------+---------------------+---------------------+--------------------+-----------------------+------------------+---------------------+
| Database|TTL(ms)|SchemaReplicationFactor|DataReplicationFactor|TimePartitionInterval|SchemaRegionGroupNum|MaxSchemaRegionGroupNum|DataRegionGroupNum|MaxDataRegionGroupNum|
+------------------+-------+-----------------------+---------------------+---------------------+--------------------+-----------------------+------------------+---------------------+
| factory| INF| 1| 1| 604800000| 1| 1| 2| 2|
|information_schema| INF| null| null| null| null| null| null| null|
| viewdb| INF| 1| 1| 604800000| 0| 1| 0| 2|
+------------------+-------+-----------------------+---------------------+---------------------+--------------------+-----------------------+------------------+---------------------+
COUNT DATABASES; -- V2.0.11+
-- 修改属性(仅支持 TTL / MAX_SCHEMA_REGION_GROUP_NUM / MAX_DATA_REGION_GROUP_NUM)
ALTER DATABASE factory SET PROPERTIES TTL=63072000000;
-- 删除(连带库内所有表和数据一并删除)
DROP DATABASE IF EXISTS factory;
2. 表 DDL
-- 创建
CREATE TABLE IF NOT EXISTS factory.device_condition (
time TIMESTAMP TIME, -- 时间列 / 树模型中 time 是严格保留字,不允许使用;但表模型中可以。
device_id STRING TAG, -- 设备编号(标识)
site STRING TAG, -- 车间
device_type STRING TAG, -- 设备类型
model STRING ATTRIBUTE, -- 型号(属性,可改)
manufacturer STRING ATTRIBUTE, -- 制造商
install_date STRING ATTRIBUTE, -- 安装日期
temperature FLOAT FIELD, -- 温度
pressure FLOAT FIELD, -- 压力
speed DOUBLE FIELD, -- 转速
power DOUBLE FIELD, -- 功率
running BOOLEAN FIELD, -- 运行状态
energy DOUBLE FIELD -- 累计能耗
) COMMENT '设备工况表' WITH (TTL=31536000000);
或者 带列注释:
CREATE TABLE IF NOT EXISTS ods_vsp_123.ods_devices_vehicles_123 (
time TIMESTAMP TIME COMMENT '时间列',
device_id STRING TAG COMMENT '设备编号(标识)',
site STRING TAG COMMENT '车间',
device_type STRING TAG COMMENT '设备类型',
model STRING ATTRIBUTE COMMENT '型号(属性,可改)',
manufacturer STRING ATTRIBUTE COMMENT '制造商',
install_date STRING ATTRIBUTE COMMENT '安装日期',
temperature FLOAT FIELD COMMENT '温度',
pressure FLOAT FIELD COMMENT '压力',
speed DOUBLE FIELD COMMENT '转速',
power DOUBLE FIELD COMMENT '功率',
running BOOLEAN FIELD COMMENT '运行状态',
energy DOUBLE FIELD COMMENT '累计能耗'
) COMMENT '设备工况表' WITH (TTL=31536000000);
-- 查看
SHOW TABLES FROM factory; -- 或 SHOW TABLES;(需先 USE)
IoTDB:factory> SHOW TABLES;
+----------------+-----------+
| TableName| TTL(ms)|
+----------------+-----------+
|device_condition|31536000000|
| device_monitor| INF|
+----------------+-----------+
Total line number = 2
It costs 0.002s
IoTDB:factory> SHOW TABLES DETAILS FROM factory;
+----------------+-----------+------+----------+----------+
| TableName| TTL(ms)|Status| Comment| TableType|
+----------------+-----------+------+----------+----------+
|device_condition|31536000000| USING|设备工况表|BASE TABLE|
| device_monitor| INF| USING| null|BASE TABLE|
+----------------+-----------+------+----------+----------+
Total line number = 2
It costs 0.003s
IoTDB:factory> DESC factory.device_condition;
+------------+---------+---------+
| ColumnName| DataType| Category|
+------------+---------+---------+
| time|TIMESTAMP| TIME|
| device_id| STRING| TAG|
| site| STRING| TAG|
| device_type| STRING| TAG|
| model| STRING|ATTRIBUTE|
|manufacturer| STRING|ATTRIBUTE|
|install_date| STRING|ATTRIBUTE|
| temperature| FLOAT| FIELD|
| pressure| FLOAT| FIELD|
| speed| DOUBLE| FIELD|
| power| DOUBLE| FIELD|
| running| BOOLEAN| FIELD|
| energy| DOUBLE| FIELD|
+------------+---------+---------+
Total line number = 13
It costs 0.004s
IoTDB:factory> DESC factory.device_condition DETAILS; -- 含列状态
+------------+---------+---------+------+-------+
| ColumnName| DataType| Category|Status|Comment|
+------------+---------+---------+------+-------+
| time|TIMESTAMP| TIME| USING| null|
| device_id| STRING| TAG| USING| null|
| site| STRING| TAG| USING| null|
| device_type| STRING| TAG| USING| null|
| model| STRING|ATTRIBUTE| USING| null|
|manufacturer| STRING|ATTRIBUTE| USING| null|
|install_date| STRING|ATTRIBUTE| USING| null|
| temperature| FLOAT| FIELD| USING| null|
| pressure| FLOAT| FIELD| USING| null|
| speed| DOUBLE| FIELD| USING| null|
| power| DOUBLE| FIELD| USING| null|
| running| BOOLEAN| FIELD| USING| null|
| energy| DOUBLE| FIELD| USING| null|
+------------+---------+---------+------+-------+
Total line number = 13
It costs 0.007s
IoTDB:factory> SHOW CREATE TABLE factory.device_condition; -- V2.0.5+,返回完整建表语句
+----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table|
Create Table|
+----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------+
|device_condition|CREATE TABLE "device_condition" ("time" TIMESTAMP TIME,"device_id" STRING TAG,"site" STRING TAG,"device_type" STRING TAG,"model" STRING ATTRIBUTE,"manufacturer" STRING ATTRIBUTE,"install_date" STRING ATTRIBUTE,"temperature" FLOAT FIELD,
"pressure" FLOAT FIELD,"speed" DOUBLE FIELD,"power" DOUBLE FIELD,"running" BOOLEAN FIELD,"energy" DOUBLE FIELD) COMMENT '设备工况表' WITH (ttl=31536000000)|
+----------------+--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------+
Total line number = 1
It costs 0.003s
-- 修改:加列 / 删列(只能删 ATTRIBUTE 和 FIELD,TAG 不可删)/ 改 TTL / 注释
ALTER TABLE factory.device_condition ADD COLUMN IF NOT EXISTS vibration FLOAT FIELD COMMENT '振动';
ALTER TABLE factory.device_condition DROP COLUMN IF EXISTS vibration;
ALTER TABLE factory.device_condition SET PROPERTIES TTL=15768000000;
COMMENT ON TABLE factory.device_condition IS '设备工况表 2026 版';
COMMENT ON COLUMN factory.device_condition.power IS '实时功率 kW';
-- 删除表
DROP TABLE IF EXISTS factory.device_condition;
3. 数据 DML(增 / 改 / 删)
- 插入数据
-- 增:单条或多行写入(未指定的列自动补 NULL)
INSERT INTO factory.device_condition
(time, device_id, site, device_type, model, temperature, pressure, speed, power, running, energy)
VALUES
('2026-10-12 08:00:00', 'DEV-001', '车间A', '压缩机', 'M300', 36.5, 0.82, 1200.0, 45.2, true, 12.5),
('2026-10-12 08:01:00', 'DEV-001', '车间A', '压缩机', 'M300', 36.7, 0.83, 1210.0, 45.8, true, 12.7),
('2026-10-12 08:00:00', 'DEV-002', '车间B', '风机', 'F200', 41.2, 0.65, 1350.5, 50.8, true, 15.1);
-- 部分列写入
INSERT INTO factory.device_condition (time, device_id, site, temperature)
VALUES ('2026-10-12 08:05:00', 'DEV-003', '车间A', 33.1);
- 查询写回(V2.0.6+,目标表须已存在)
-- 1. 先建目标归档表(结构要与 SELECT 出来的列对齐)
CREATE TABLE IF NOT EXISTS factory.device_condition_archive (
time TIMESTAMP TIME,
device_id STRING TAG,
site STRING TAG,
device_type STRING TAG,
model STRING ATTRIBUTE,
temperature FLOAT FIELD,
pressure FLOAT FIELD,
speed DOUBLE FIELD,
power DOUBLE FIELD,
running BOOLEAN FIELD,
energy DOUBLE FIELD
) COMMENT '设备工况归档表' WITH (TTL=63072000000);
-- 2. 再执行查询写回
INSERT INTO factory.device_condition_archive
SELECT time, device_id, site, device_type, model, temperature, pressure, speed, power, running, energy
FROM factory.device_condition WHERE site = '车间A';
-- 3. 校验
IoTDB:factory> SELECT * FROM factory.device_condition_archive;
+-----------------------------+---------+-----+-----------+-----+-----------+--------+------+-----+-------+------+
| time|device_id| site|device_type|model|temperature|pressure| speed|power|running|energy|
+-----------------------------+---------+-----+-----------+-----+-----------+--------+------+-----+-------+------+
|2026-10-12T08:05:00.000+08:00| DEV-003|车间A| null| null| 33.1| null| null| null| null| null|
|2026-10-12T08:00:00.000+08:00| DEV-001|车间A| 压缩机| M300| 36.5| 0.82|1200.0| 45.2| true| 12.5|
|2026-10-12T08:01:00.000+08:00| DEV-001|车间A| 压缩机| M300| 36.7| 0.83|1210.0| 45.8| true| 12.7|
+-----------------------------+---------+-----+-----------+-----+-----------+--------+------+-----+-------+------+
Total line number = 3
It costs 0.017s
SELECT COUNT(*) AS copied_rows FROM factory.device_condition_archive;
- 数据的修改与删除
-- 改:UPDATE 仅允许修改 ATTRIBUTE 列,WHERE 只能用 TAG / ATTRIBUTE 条件
UPDATE factory.device_condition SET model = 'M300-Pro'
WHERE device_id = 'DEV-001' AND site = '车间A';
-- 改:FIELD 值不支持 UPDATE,只能"删了重插" 或用相同时间戳重新 INSERT 覆盖
INSERT INTO factory.device_condition (time, device_id, site, temperature)
VALUES ('2026-10-12 08:00:00', 'DEV-001', '车间A', 36.9); -- 同时间戳覆盖原值
-- 删:按标签 / 时间条件删除(WHERE 仅支持时间比较和 TAG 等于字符串,可用 AND/OR 组合)
DELETE FROM factory.device_condition WHERE device_id = 'DEV-003';
DELETE FROM factory.device_condition
WHERE time >= 2026-10-12 08:00:00 AND time <= 2026-10-12 08:30:00 AND device_id = 'DEV-002';
-- 删:清空整表
DELETE FROM factory.device_condition;
-- 删:删除整台设备及其全部数据
IoTDB:factory> DELETE DEVICES FROM factory.device_condition WHERE device_id = 'DEV-002';
+----------------------+
|num_of_deleted_devices|
+----------------------+
| 1|
+----------------------+
Total line number = 1
It costs 0.140s
4. 数据 DQL(查询 + 聚合)
-- 基础查询
IoTDB:factory> SELECT * FROM factory.device_condition;
+-----------------------------+---------+-----+-----------+-----+------------+------------+-----------+--------+------+-----+-------+------+
| time|device_id| site|device_type|model|manufacturer|install_date|temperature|pressure| speed|power|running|energy|
+-----------------------------+---------+-----+-----------+-----+------------+------------+-----------+--------+------+-----+-------+------+
|2026-10-12T08:05:00.000+08:00| DEV-003|车间A| null| null| null| null| 33.1| null| null| null| null| null|
|2026-10-12T08:00:00.000+08:00| DEV-001|车间A| 压缩机| M300| null| null| 36.5| 0.82|1200.0| 45.2| true| 12.5|
|2026-10-12T08:01:00.000+08:00| DEV-001|车间A| 压缩机| M300| null| null| 36.7| 0.83|1210.0| 45.8| true| 12.7|
|2026-10-12T08:00:00.000+08:00| DEV-002|车间B| 风机| F200| null| null| 41.2| 0.65|1350.5| 50.8| true| 15.1|
+-----------------------------+---------+-----+-----------+-----+------------+------------+-----------+--------+------+-----+-------+------+
Total line number = 4
It costs 0.019s
SELECT time, device_id, temperature, pressure, speed
FROM factory.device_condition
WHERE device_id = 'DEV-001' AND time >= 2026-10-12 08:00:00
ORDER BY time DESC LIMIT 100;
-- 每台设备最新工况值
SELECT device_id, LAST(temperature), LAST_BY(time, temperature)
FROM factory.device_condition GROUP BY device_id;
-- 全局聚合(无 GROUP BY 时 SELECT 必须全是聚合函数;只有 COUNT 支持 *)
SELECT COUNT(*) AS total_rows,
AVG(temperature) AS avg_temp,
MAX(temperature) AS max_temp,
MIN(pressure) AS min_pressure,
SUM(energy) AS total_energy
FROM factory.device_condition;
IoTDB:factory> SELECT COUNT(*) AS total_rows, AVG(temperature) AS avg_temp, MAX(temperature) AS max_temp, MIN(pressure) AS min_pressure, SUM(energy) AS total_energy FROM factory.device_condition;
+----------+--------+--------+------------+------------+
|total_rows|avg_temp|max_temp|min_pressure|total_energy|
+----------+--------+--------+------------+------------+
| 4| 36.875| 41.2| 0.65| 40.3|
+----------+--------+--------+------------+------------+
Total line number = 1
It costs 0.020s
-- 按设备分组聚合(SELECT 项必须是聚合函数或出现在 GROUP BY 中)
SELECT device_id,
COUNT(*) AS record_cnt,
AVG(temperature) AS avg_temp,
MAX(speed) AS max_speed,
SUM(energy) AS total_energy
FROM factory.device_condition
GROUP BY device_id;
IoTDB:factory> SELECT device_id, COUNT(*) AS record_cnt, AVG(temperature) AS avg_temp, MAX(speed) AS max_speed, SUM(energy) AS total_energy FROM factory.device_condition GROUP BY device_id;
+---------+----------+------------------+---------+------------+
|device_id|record_cnt| avg_temp|max_speed|total_energy|
+---------+----------+------------------+---------+------------+
| DEV-001| 2| 36.60000038146973| 1210.0| 25.2|
| DEV-002| 1| 41.20000076293945| 1350.5| 15.1|
| DEV-003| 1|33.099998474121094| null| null|
+---------+----------+------------------+---------+------------+
Total line number = 3
It costs 0.021s
-- 多维分组:车间 × 设备类型
SELECT site, device_type, AVG(power) AS avg_power, MAX(speed) AS max_speed
FROM factory.device_condition
GROUP BY site, device_type;
IoTDB:factory> SELECT site, device_type, AVG(power) AS avg_power, MAX(speed) AS max_speed FROM factory.device_condition GROUP BY site, device_type;
+-----+-----------+---------+---------+
| site|device_type|avg_power|max_speed|
+-----+-----------+---------+---------+
|车间A| 压缩机| 45.5| 1210.0|
|车间A| null| null| null|
|车间B| 风机| 50.8| 1350.5|
+-----+-----------+---------+---------+
Total line number = 3
It costs 0.021s
-- 时间降采样:每小时平均温度(date_bin 时间分桶 + GROUP BY 1 引用第一列;V2.0.11.1+ 可直接 GROUP BY 别名)
SELECT date_bin(1h, time) AS hour_bin, device_id, AVG(temperature) AS avg_temp
FROM factory.device_condition
WHERE time >= 2026-10-12 00:00:00
GROUP BY 1, device_id;
IoTDB:factory> SELECT date_bin(1h, time) AS hour_bin, device_id, AVG(temperature) AS avg_temp FROM factory.device_condition WHERE time >= 2026-10-12 00:00:00 GROUP BY 1, device_id;
+-----------------------------+---------+------------------+
| hour_bin|device_id| avg_temp|
+-----------------------------+---------+------------------+
|2026-10-12T08:00:00.000+08:00| DEV-001| 36.60000038146973|
|2026-10-12T08:00:00.000+08:00| DEV-002| 41.20000076293945|
|2026-10-12T08:00:00.000+08:00| DEV-003|33.099998474121094|
+-----------------------------+---------+------------------+
Total line number = 3
It costs 0.025s
-- HAVING 过滤分组结果
SELECT device_id, AVG(temperature) AS avg_temp
FROM factory.device_condition
GROUP BY device_id
HAVING AVG(temperature) > 40;
-- 子查询 + 二次聚合:筛选平均温度 > 40 且组内记录数 >= 2 的车间设备组合
SELECT site, device_id
FROM (
SELECT date_bin(10m, time) AS t, site, device_id, AVG(temperature) AS temp
FROM factory.device_condition
WHERE time >= 2026-10-12 00:00:00
GROUP BY 1, site, device_id
)
WHERE temp > 40
GROUP BY site, device_id
HAVING COUNT(*) >= 2;
要点提示
- 没有传统意义的"改历史测点":FIELD 是时序值,靠同时间戳覆盖写入;属性值用
UPDATE或INSERT更新;改标签(TAG)需DELETE DEVICES+ 重插。 - DELETE 的 WHERE 限制较严:只支持时间条件 + TAG 等于字符串字面量,不能按 FIELD 值过滤。
- 版本差异:
SHOW CREATE TABLEV2.0.5+、INSERT INTO ... SELECTV2.0.6+、自定义时间列名 V2.0.8+、COUNT DATABASESV2.0.11+、GROUP BY别名 V2.0.11.1+。 - 聚合约束:
GROUP BY后 SELECT 的裸列必须出现在分组键里;只有COUNT可与*搭配。
Z FAQ for Apache IoTDB 使用
Q: Apache IoTDB 树模型模式下,新增测点的 DDL 时,是否能要求和之前老测点做时间对齐?不能
- 结论:不能。 IoTDB 树模型没有“在新增测点的 DDL 里声明与老测点时间对齐”这样的语法。
几点事实(均出自官方文档):
1. “对齐”是设备(实体)级属性,创建时一次定死
对齐通过 CREATE ALIGNED TIMESERIES 在同一批测点创建时整体设定,让这一组测点共享同一个时间戳列(时间轴在内存/磁盘里只存一份),而不是每个测点各存一份。
2. 官方明确:【对齐序列】与【非对齐序列】不能混在【同一个实体】下
文档原话:“不可以在对齐序列所属的实体下创建非对齐的序列,不可以在非对齐序列所属的实体下创建对齐序列。”
也就是说,如果【老测点】是在某设备下用【默认方式】(非对齐)建的,那么【新测点】建在同一个设备下,只能继续是【非对齐】,无法“对齐”到【旧测点】。反过来也一样。
3. 所以要【实现对齐】,必须在一开始就规划
要么在建该设备第一批测点时就用 CREATE ALIGNED TIMESERIES root.sg.d1(s1, s2, ...) 一起建,要么用模板 CREATE SCHEMA TEMPLATE t2 ALIGNED (lat, lon) 统一建模。
历史已经按【非对齐】建好的测点,无法通过后续 DDL 追溯改成对齐,只能重建,或把需要对齐的测点规划到一个新的对齐设备/模板下。
一个概念澄清,避免踩坑:“对齐”在 IoTDB 里主要指【物理存储布局】(共享时间列、紧凑存储),不是【查询语义的强制约束】。【多测点数据】本来就可以按【同一时间戳写入】、查询时按【时间轴对齐】取数——如果你关心的只是“数据天然共用同一时间轴”,那只是【写入约定】,根本不需要对齐这个 DDL 属性。
Q: 树模型的对齐与不对齐的本质区别?
- 树模型下“对齐/非对齐”的本质差别就是【时间戳列】是否【物理共享】:
- 对齐 = 一组测点共用一个时间轴列
- 非对齐 = 每个测点各存各的时间列
这不是查询语义的差别,而是存储布局的差别。对比如下:
| 对比维度 | 对齐(Aligned) | 非对齐(默认) |
|---|---|---|
| 时间轴存储 | 一组测点共享一个时间戳列,内存/磁盘只存一份 | 每个测点各自独立存储自己的时间戳列 |
| 建点方式 | CREATE ALIGNED TIMESERIES,同一批整体声明,最好同时创建 |
CREATE TIMESERIES 单个创建(默认) |
| 数据组织 | 同一时间戳的多测点值聚成一行,行内缺值补 NULL | 每个测点单独成序列,各自成行 |
| 存储/压缩 | 紧凑,同时间点数据压缩率高、省空间 | 冗余,时间列多份存储,占用更大 |
| 设备约束 | 对齐设备下不能再建非对齐测点 | 非对齐设备下不能再建对齐测点 |
| 插入方式 | INSERT ... ALIGNED VALUES |
普通 INSERT ... VALUES(不带 aligned) |
| 缺失值 | 允许某测点在该时间戳为 NULL,时间轴仍共享 | 各测点时间轴独立,天然不必对齐,无补空问题 |
| 查询 | 每个测点仍可单独查询 | 每个测点单独查询 |
| 适用场景 | 同设备多测点同频、同时刻采集(如同一传感器的多个物理量) | 测点采样频率/时间点差异大、独立变化 |
| 后期扩展 | 【对齐设备】可继续用 CREATE ALIGNED TIMESERIES/ALTER DEVICE TEMPLATE t2 ADD (speed FLOAT); 加【对齐测点】 |
【非对齐设备】可继续 CREATE TIMESERIES 加测点;但永远无法转成对齐(只能重建) |
- 模板测点是 “写时实体化”:在写入数据前(或未开启自动注册时),新测点不会真正创建。所以
alter add后,新测点要在实际写入时才对全批设备生效。 - 对齐 / 非对齐仍受设备级约束约束:t2 是 ALIGNED 模板,挂载它的设备是 aligned 设备,所以追加的测点只能走模板(对齐)路径,不能在该设备下单独
CREATE TIMESERIES建非对齐测点;反过来,非对齐模板(如 t1)加的新测点也是非对齐。
总结:对齐是“行优先”的紧凑存储(一行为多个同时刻测点),非对齐是“列独立”的时间轴存储。
选型: 这组测点是否长期同频、同时刻出现:是就对齐,否就非对齐。``
Q: 用模板 CREATE SCHEMA TEMPLATE t2 ALIGNED (lat, lon) 统一建模,能支持后期对同一批设备追加时间对齐的新测点?
这个问题涉及模板(schema template)变更后对已挂载设备是否生效。
- 结论:能,而且模板方式正是为此设计的。 官方明确:改一次模板,所有已激活该模板的设备一次性新增物理量。
具体做法(两条途径):
1、途径一:【修改模板】统一追加(推荐)
ALTER DEVICE TEMPLATE t2 ADD (speed FLOAT);
- 一条 DDL 给所有挂载并激活 t2 的设备(root.sg1.d1、d2、d3…)统一新增
speed测点。 - 因为 t2 创建时是
ALIGNED(模板级共享时间属性),追加进来的speed继承模板的对齐属性,与原有的lat、lon共享同一时间轴,即新测点与老测点时间对齐。
2、途径二:写入时【自动扩展】
官方文档:“向已挂载模板路径下的设备写入数据,若写入请求中的物理量不在模板中,将自动扩展模板。”
即: 直接按【对齐方式】向该设备写新测点数据,模板自动补上该测点,无需显式建点。
两个注意事项:
- 模板测点是“写时实体化”:在写入数据前(或未开启自动注册时),新测点不会真正创建。所以
alter add后,新测点要在实际写入时才对全批设备生效。 - 对齐/非对齐仍受设备级约束约束:t2 是 ALIGNED 模板,挂载它的设备是 aligned 设备,所以追加的测点只能走模板(对齐)路径,不能在该设备下单独
CREATE TIMESERIES建非对齐测点;反过来,非对齐模板(如 t1)加的新测点也是非对齐。
所以回到原始场景:模板 + ALIGNED 是兼顾“统一建模”和“后期整批追加对齐测点”的正解——用 ALTER DEVICE TEMPLATE 即可对同一批设备批量追加时间对齐的新测点,而不用逐设备建点。
Q: iotdb树模型、表模型的测点列field支持的数据类型? (必读)
基于官方最新版(V2.0.x)数据类型的完整定义,树模型测点(measurement)与表模型列(field)各自支持的数据类型:
底层基本数据类型(两模型共用)
IoTDB 支持以下十种基本类型作为值类型,树模型【测点列】与表模型【测点列】都以这组类型为底座(V2.0.8 起表模型额外引入 OBJECT):
| 类型 | 说明 |
|---|---|
BOOLEAN |
布尔值 |
INT32 |
32 位整型 |
INT64 |
64 位长整型 |
FLOAT |
单精度浮点 |
DOUBLE |
双精度浮点 |
TEXT |
长字符串(不推荐,无过滤优化) |
STRING |
字符串(带统计信息,可优化值过滤查询) |
BLOB |
大二进制对象 |
TIMESTAMP |
时间戳(精确时刻) |
DATE |
日期(仅日历日期) |
OBJECT |
大二进制对象(表模型专用,V2.0.8+,写放大/查询方式与 BLOB 不同) |
STRING与TEXT均存文本,区别在于 STRING 附带统计信息可优化过滤查询;TEXT 适合超长串但无优化。
树模型测点(Measurement)
CREATE TIMESERIES ... WITH DATATYPE=... 时,测点数据类型可取:BOOLEAN、INT32、INT64、FLOAT、DOUBLE、TEXT、STRING、BLOB、DATE、TIMESTAMP(后两者 1.3+ 引入,2.x 稳定)。树模型测点不支持 OBJECT。
表模型列(Column)按类别区分
表模型每列有明确 Category,类型约束不同:
| 列类别 | 允许的数据类型 | 说明 |
|---|---|---|
TIME |
仅 TIMESTAMP |
每表必须且仅有一个时间列,未指定时自动添加 |
TAG |
仅 STRING |
设备标识,可作复合主键,不可删除 |
ATTRIBUTE |
仅 STRING |
设备属性 |
FIELD(测点列,默认) |
BOOLEAN/INT32/INT64/FLOAT/DOUBLE/TEXT/STRING/BLOB/DATE/TIMESTAMP/OBJECT |
未标注类别时默认即为 FIELD |
建表示例:
CREATE TABLE table1 (
time TIMESTAMP TIME, -- 时间列
device_id STRING TAG, -- 标签列
model_id STRING ATTRIBUTE, -- 属性列
temperature FLOAT FIELD, -- 测点列
arrival_time TIMESTAMP FIELD -- 测点列可为时间戳
) WITH (TTL=31536000000);
关键要点
- 测点列类型:两模型的测点列都覆盖全部数值/文本/二进制/时间类型;表模型额外多了
OBJECT(2.0.8+,适合低频大对象,返回元信息,用READ_OBJECT取原始内容)。 - TAG/ATTRIBUTE 列强制 STRING,这是表模型元数据列与树模型测点的最大差异。
- 类型兼容写入:写入类型与注册类型不一致时,兼容则自动转换、不兼容则报错(如
INT64可兼容INT32/INT64/TIMESTAMP;DOUBLE兼容INT32/INT64/FLOAT/DOUBLE/TIMESTAMP)。 - FLOAT/DOUBLE 精度:RLE/TS_2DIFF 编码下可通过
MAX_POINT_NUMBER指定小数位,默认取配置float_precision(2 位)。
Q: 哪些IoTDB 的客户端有哪些? 官方 JDBC / 官方 CLI / DBX 数据库连接工具 (必读)
- 官方 JDBC
iotdb.version = 2.0.11
<dependency>
<groupId>org.apache.iotdb</groupId>
<artifactId>iotdb-jdbc</artifactId>
<version>${iotdb.version}</version>
</dependency>
- 官方 CLI
/d/Programs/Apache-loTDB/apache-iotdb-2.0.11-all-bin
$ ./sbin/windows/start-cli.bat -h 192.168.xxx.xxx -p 6667 -sql_dialect table
---------------------
Starting IoTDB Cli
---------------------
_____ _________ ______ ______
|_ _| | _ _ ||_ _ `.|_ _ \
| | .--.|_/ | | \_| | | `. \ | |_) |
| | / .'`\ \ | | | | | | | __'.
_| |_| \__. | _| |_ _| |_.' /_| |__) |
|_____|'.__.' |_____| |______.'|_______/ version 2.0.11 (Build: 7c0de06)
Successfully login at 192.168.xxx.xxx:6667
IoTDB>

- DBX 数据库连接工具


Y 推荐文献
- Apache IoTDB
- https://iotdb.apache.org/zh/UserGuide/latest/Background-knowledge/Data-Type.html (支持的数据类型)
- https://iotdb.apache.org/zh/UserGuide/latest/Basic-Concept/Operate-Metadata_apache.html (设备模板)
- SeaTunnel 所需的 IoTDB connector 下载URL: https://mvnrepository.com/artifact/org.apache.seatunnel/connector-iotdb/2.3.13
X 参考文献
本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!


浙公网安备 33010602011771号