Apache IoTDB 全面操作指南:从数据库管理到数据写入实战
本文围绕 Apache IoTDB 时序数据库,从多维度展开全面操作指南。先详解数据库管理,包括创建、查看、删除、统计数量、设置 TTL 及配置异构数据库,明确命名规则与参数约束;再阐述设备模板管理,覆盖创建、挂载、激活、查看、解除与卸载等流程,实现同类型设备元数据共享;接着深入时间序列管理,介绍创建、删除、查看、统计及标签属性管理,强调对齐序列特性;还讲解路径查询,说明路径语法、子路径与子节点查看、节点统计及设备查看统计;最后详述数据写入方式,含 CLI、原生接口、REST API、MQTT 及批量导入,并给出无模式写入方案与最佳实践,助力开发者高效实现物联网时序数据存储管理。
在物联网(IoT)场景里,时序数据的高效存储、管理和写入可是核心需求。Apache IoTDB 作为一款专门为时序数据设计的数据库,凭着高吞吐、低延迟、高压缩率这些亮眼特性,在物联网领域圈粉无数,成了很多开发者的首选。今天这篇文章,就基于官方操作规范,从数据库管理、设备模板管理、时间序列管理、路径查询到数据写入,把 IoTDB 的核心操作拆解得明明白白,再配上详细的代码示例和场景说明,帮大家快速上手,熟练运用这款工具。
一、数据库管理:IoTDB 数据存储的基础
数据库(Database)是 IoTDB 中时序数据的顶层存储单元,所有时间序列都得归到特定数据库下。这一节,咱们就详细说说数据库的创建、查看、删除、数量统计、TTL 设置以及异构数据库配置,从基础操作到进阶技巧,一步一步讲清楚。
1.1 创建数据库(CREATE DATABASE)
用 IoTDB 做开发,第一步就是创建数据库。这里有个关键规则得记牢:父子节点不能重复设为数据库。另外,节点名的命名规范和系统兼容性也得留意,不然很容易出问题。
核心语法
-- 基础创建:指定数据库路径(建议大家只创建1个数据库,管理起来更方便)
IoTDB > CREATE DATABASE root.ln
-- 错误示例:要是父节点已经是数据库了,子节点就没法再创建数据库了
IoTDB > CREATE DATABASE root.ln.wf01
-- 系统报错:Msg: 300: root.ln has already been created as database.
节点名命名规则
| 允许字符 | 特殊情况处理 | 系统兼容性 |
|---|---|---|
| 中英文字符、数字、下划线(_)、英文句号(.)、反引号(`) | 1. 纯数字(比如12345)得用反引号包起来 2. 有歧义的字符(像db.01、_temp)也得用反引号包起来 3. 节点名里要是有反引号,就得用两个反引号表示一个(比如 db123``得写成db123```) |
Windows 系统不区分大小写(比如root.ln和root.LN会被当成同一个数据库) |
示例:特殊节点名创建
-- 纯数字节点名
IoTDB > CREATE DATABASE root.`12345`
-- 含歧义字符节点名
IoTDB > CREATE DATABASE root.`db.01`
-- 含反引号的节点名
IoTDB > CREATE DATABASE root.`db123```
1.2 查看数据库(SHOW DATABASES)
数据库创建好后,想知道所有数据库的信息,比如 TTL、副本数、时间分区间隔这些关键配置,用 SHOW DATABASES 命令就行。
核心语法与示例
-- 查看所有数据库
IoTDB > SHOW DATABASES
-- 按路径模式过滤:查看root下所有子数据库(*代表单层,**代表多层)
IoTDB > SHOW DATABASES root.* -- 匹配root的直接子节点数据库
IoTDB > SHOW DATABASES root.** -- 匹配root下所有层级数据库
执行结果解析
+-------------+----+-------------------------+-----------------------+-----------------------+
| database| ttl|schema_replication_factor|data_replication_factor|time_partition_interval|
+-------------+----+-------------------------+-----------------------+-----------------------+
| root.sgcc|null| 2| 2| 604800| -- 时间分区间隔:604800秒,也就是7天
| root.ln|null| 2| 2| 604800|
+-------------+----+-------------------------+-----------------------+-----------------------+
Total line number = 2
It costs 0.060s
- ttl:数据保留时间(默认是null,意思就是永久保留);
- schema_replication_factor:元数据副本数(这么设置是为了保证元数据高可用);
- data_replication_factor:数据副本数(主要是为了确保数据可靠,不怕丢失);
- time_partition_interval:时间分区间隔(默认7天,按照时间维度拆分数据文件,方便管理)。
1.3 删除数据库(DELETE DATABASE)
删除数据库可得小心,一旦删了,它下面所有的时间序列和数据也会跟着一起没了。不过这个命令支持按路径模式批量删除,操作起来还算灵活。
核心语法与示例
-- 删除单个数据库
IoTDB > DELETE DATABASE root.ln
-- 批量删除:删除root下所有数据库(这操作风险高,大家一定要谨慎使用!)
IoTDB > DELETE DATABASE root.**
1.4 统计数据库数量(COUNT DATABASES)
想知道符合指定路径模式的数据库有多少个,用 COUNT DATABASES 命令就可以,不管是精确匹配还是模糊匹配都支持。
核心语法与示例
-- 统计所有数据库数量
IoTDB > COUNT DATABASES
-- 按路径模式统计:root下直接子数据库数量
IoTDB > COUNT DATABASES root.*
-- 精确统计:root.sgcc数据库数量(存在的话就是1,不存在就是0)
IoTDB > COUNT DATABASES root.sgcc
执行结果示例
-- 统计所有数据库(一共3个)
+-------------+
| Database|
+-------------+
| 3|
+-------------+
-- 统计root.sgcc.*(没有匹配的数据库,结果就是0)
+-------------+
| Database|
+-------------+
| 0|
+-------------+
1.5 数据保留时间(TTL):自动清理过期数据
TTL(Time-To-Live)简单说就是设置设备级的数据保留时间,数据一旦过期,系统会自动删掉它。这样做能有效控制磁盘占用,还能优化查询性能,是个很实用的功能。
TTL 核心特性
- 单位:默认是毫秒,就算你在配置文件里改了时间精度,TTL 还是以毫秒为单位;
- 生效粒度:是按设备(Device)生效的,系统会根据路径匹配所有设备然后设置 TTL;
- 过期判断:判断数据过没过期,看的是数据点时间,不是数据写入时间;
- 删除机制:过期的数据查不到,但不会马上物理删除,得等文件合并的时候才会删掉;
- 规则上限:系统最多支持1000条 TTL 规则,要是想加新规则,得先把旧规则删掉。
TTL 路径规则
| 路径类型 | 合格示例 | 不合格示例 | 说明 |
|---|---|---|---|
| 前缀路径(必须以**结尾) | root.、root.db. | root..db、root.**.db. | 匹配路径下所有设备 |
| 具体数据库/设备路径(不带*) | root.db、root.db.device1 | root.db.* | 要是路径是数据库,会自动扩展成root.db.** |
设置 TTL(SET TTL)
-- 为root.sg下所有设备设置TTL:360000毫秒,也就是1小时
-- 路径root.sg是数据库,会自动扩展成root.sg.**
IoTDB > SET TTL TO root.sg 360000
-- 为具体设备设置TTL:root.db.device1保留86400000毫秒,也就是1天
IoTDB > SET TTL TO root.db.device1 86400000
-- 设置TTL为无限大(用INF关键字就行)
IoTDB > SET TTL TO root.** INF
取消 TTL(UNSET TTL)
-- 取消root.ln下所有设备的TTL(这样数据就会永久保留了)
IoTDB > UNSET TTL FROM root.ln
-- 取消root.sgcc下所有设备的TTL
IoTDB > UNSET TTL FROM root.sgcc.**
-- 取消所有设备的TTL(新旧语法都能用,新语法更推荐)
IoTDB > UNSET TTL FROM root.** -- 新语法(推荐)
IoTDB > UNSET TTL TO root.** -- 旧语法(功能一样)
查看 TTL(SHOW TTL)
-- 查看所有TTL规则
IoTDB > SHOW ALL TTL
+--------------+--------+
| path| TTL|
+--------------+--------+
| root.**|55555555| -- 所有设备保留55555555毫秒
| root.sg2.a.**|44440000| -- root.sg2.a下设备保留44440000毫秒
+--------------+--------+
-- 查看指定路径的TTL规则
IoTDB > SHOW TTL ON root.db.**
+--------------+--------+
| path| TTL|
+--------------+--------+
| root.db.**|55555555|
| root.db.a.**|44440000|
+--------------+--------+
-- 查看设备的TTL(所有设备都有TTL,INF表示无限大)
IoTDB > SHOW DEVICES
+---------------+---------+---------+
| Device|IsAligned| TTL|
+---------------+---------+---------+
|root.sg.device1| false| 36000000| -- 保留1小时
|root.sg.device2| true| INF| -- 永久保留
+---------------+---------+---------+
1.6 异构数据库(进阶):自定义数据库参数
异构数据库能让不同数据库配置不一样的参数,比如副本数、TTL、分区策略这些,对于有多种数据存储需求的场景特别有用。
支持的异构参数
| 参数名 | 类型 | 描述 | 约束 |
|---|---|---|---|
| TTL | Long | 数据库级数据保留时间 | 必须是正整数 |
| SCHEMA_REPLICATION_FACTOR | Integer | 元数据副本数 | 不能超过已经部署的DataNode数量 |
| DATA_REPLICATION_FACTOR | Integer | 数据副本数 | 不能超过已经部署的DataNode数量 |
| SCHEMA_REGION_GROUP_NUM | Integer | SchemaRegionGroup数量 | 和配置文件里的schema_region_group_extension_policy有关联 |
| DATA_REGION_GROUP_NUM | Integer | DataRegionGroup数量 | 和配置文件里的data_region_group_extension_policy有关联 |
创建时配置异构参数
-- 创建root.db数据库,设置元数据副本数1、数据副本数3、SchemaRegionGroup1个、DataRegionGroup2个
IoTDB > CREATE DATABASE root.db WITH SCHEMA_REPLICATION_FACTOR=1, DATA_REPLICATION_FACTOR=3, SCHEMA_REGION_GROUP_NUM=1, DATA_REGION_GROUP_NUM=2;
运行时调整异构参数
目前只能调整 SCHEMA_REGION_GROUP_NUM 和 DATA_REGION_GROUP_NUM 这两个参数:
-- 把root.db的DataRegionGroup数量调整为3
IoTDB > ALTER DATABASE root.db WITH DATA_REGION_GROUP_NUM=3;
查看异构数据库详情
IoTDB > SHOW DATABASES DETAILS
+--------+--------+-----------------------+---------------------+---------------------+--------------------+-----------------------+-----------------------+------------------+---------------------+---------------------+
|Database| TTL|SchemaReplicationFactor|DataReplicationFactor|TimePartitionInterval|SchemaRegionGroupNum|MinSchemaRegionGroupNum|MaxSchemaRegionGroupNum|DataRegionGroupNum|MinDataRegionGroupNum|MaxDataRegionGroupNum|
+--------+--------+-----------------------+---------------------+---------------------+--------------------+-----------------------+-----------------------+------------------+---------------------+---------------------+
|root.db1| null| 1| 3| 604800000| 0| 1| 1| 0| 2| 2|
|root.db2|86400000| 1| 1| 604800000| 0| 1| 1| 0| 2| 2|
+--------+--------+-----------------------+---------------------+---------------------+--------------------+-----------------------+-----------------------+------------------+---------------------+---------------------+
二、设备模板管理:简化同类型设备元数据配置
在物联网场景中,经常会遇到大量同类型的设备,比如同一型号的传感器,它们都有相同的物理量,像温度、湿度这些。这时候用设备模板就特别方便,能实现元数据共享,既减少内存占用,又简化管理工作。
2.1 创建设备模板(CREATE DEVICE TEMPLATE)
设备模板其实就是定义了一组物理量的元数据,包括数据类型、编码、压缩方式这些,而且它还支持对齐和非对齐序列。
核心语法与示例
-- 示例1:创建非对齐序列模板(temperature是FLOAT类型,status是BOOLEAN类型)
-- 系统默认的编码方式:FLOAT用RLE,BOOLEAN用PLAIN;默认的压缩方式是SNAPPY
IoTDB > CREATE DEVICE TEMPLATE t1 (temperature FLOAT, status BOOLEAN)
-- 示例2:创建对齐序列模板(lat和lon是对齐的,得加ALIGNED关键字)
IoTDB > CREATE DEVICE TEMPLATE t2 ALIGNED (lat FLOAT, lon FLOAT)
-- 示例3:手动指定编码和压缩方式(这种适合有特殊业务场景的情况)
IoTDB > CREATE DEVICE TEMPLATE t3 (temperature FLOAT encoding=RLE, status BOOLEAN encoding=PLAIN compression=SNAPPY)
- 对齐序列:同一设备下的多个序列共用一个时间戳,像GPS的经纬度这种多指标同步采集的场景就特别适合用;
- 编码/压缩方式:得和数据类型匹配才行,比如BOOLEAN类型就不支持TS_2DIFF编码,具体的对应关系大家可以去看 IoTDB 官方的「压缩&编码」文档。
2.2 挂载设备模板(SET DEVICE TEMPLATE)
模板创建好之后,不是直接就能用的,得挂载到指定路径上才行。不过挂载之前有两个事儿得注意:一是对应的数据库得先创建好,二是路径下不能有普通序列。
核心语法与示例
-- 把模板t1挂载到root.sg1.d1这个设备路径上
IoTDB > SET DEVICE TEMPLATE t1 TO root.sg1.d1
-- 推荐这么做:把模板挂载到数据库节点上,比如root.sg1,这样就能覆盖这个数据库下所有的设备了
IoTDB > SET DEVICE TEMPLATE t2 TO root.sg1
注意事项
- 模板挂载的路径下,不能再创建普通序列了;
- 要是路径下已经创建了普通序列,就不能再挂载模板了;
- 不建议把模板挂载到数据库上层节点,比如root,不然管理起来会很混乱。
2.3 激活设备模板(CREATE TIMESERIES USING TEMPLATE)
模板挂载好之后,还得激活才能创建对应的时间序列。激活的方式有两种,大家可以根据自己的情况选。
- 自动激活:把系统的「自动注册序列」功能打开,这样写入数据的时候模板就会自动激活;
- 手动激活:用
CREATE TIMESERIES USING TEMPLATE命令提前激活。
核心语法与示例
-- 手动激活root.sg1.d1下的模板t1(这样就能创建对应的时间序列了)
IoTDB > CREATE TIMESERIES USING DEVICE TEMPLATE ON root.sg1.d1
-- 批量激活多个设备的模板
IoTDB > SET DEVICE TEMPLATE t1 TO root.sg1.d1, root.sg1.d2
IoTDB > CREATE TIMESERIES USING DEVICE TEMPLATE ON root.sg1.d1, root.sg1.d2
激活后验证
-- 查看激活后的时间序列
IoTDB > SHOW TIMESERIES root.sg1.**
+-----------------------+-----+-------------+--------+--------+-----------+----+----------+--------+-------------------+
| timeseries|alias| database|dataType|encoding|compression|tags|attributes|deadband|deadband parameters|
+-----------------------+-----+-------------+--------+--------+-----------+----+----------+--------+-------------------+
|root.sg1.d1.temperature| null| root.sg1| FLOAT| RLE| SNAPPY|null| null| null| null|
| root.sg1.d1.status| null| root.sg1| BOOLEAN| PLAIN| SNAPPY|null| null| null| null|
| root.sg1.d2.lon| null| root.sg1| FLOAT| GORILLA| SNAPPY|null| null| null| null|
| root.sg1.d2.lat| null| root.sg1| FLOAT| GORILLA| SNAPPY|null| null| null| null|
+-----------------------+-----+-------------+--------+--------+-----------+----+----------+--------+-------------------+
2.4 查看设备模板(SHOW DEVICE TEMPLATES)
想查看设备模板的相关信息,比如所有模板、模板下的物理量、模板挂载路径还有激活路径,都有对应的命令可以用。
核心语法与示例
-- 1. 查看所有设备模板
IoTDB > SHOW DEVICE TEMPLATES
+-------------+
|template name|
+-------------+
| t2|
| t1|
+-------------+
-- 2. 查看模板t1下的物理量(包括数据类型、编码、压缩方式)
IoTDB > SHOW NODES IN DEVICE TEMPLATE t1
+-----------+--------+--------+-----------+
|child nodes|dataType|encoding|compression|
+-----------+--------+--------+-----------+
|temperature| FLOAT| RLE| SNAPPY|
| status| BOOLEAN| PLAIN| SNAPPY|
+-----------+--------+--------+-----------+
-- 3. 查看模板t1的挂载路径(就算没激活也能看到)
IoTDB > SHOW PATHS SET DEVICE TEMPLATE t1
+-----------+
|child paths|
+-----------+
|root.sg1.d1|
+-----------+
-- 4. 查看模板t1的激活路径(就是已经创建了时间序列的路径)
IoTDB > SHOW PATHS USING DEVICE TEMPLATE t1
+-----------+
|child paths|
+-----------+
|root.sg1.d1|
+-----------+
2.5 解除与卸载模板(DEACTIVATE / UNSET)
如果想删除模板对应的时间序列,或者把模板收回来不用了,得先解除激活,然后再卸载模板,步骤可不能乱。
1. 解除模板激活(删除时间序列)
-- 解除root.sg1.d1下模板t1的激活(对应的时间序列也会被删除)
IoTDB > DELETE TIMESERIES OF DEVICE TEMPLATE t1 FROM root.sg1.d1
-- 也可以用下面这个等价的语法
IoTDB > DEACTIVATE DEVICE TEMPLATE t1 FROM root.sg1.d1
-- 批量解除:解除root.sg1和root.sg2下模板t1的激活
IoTDB > DELETE TIMESERIES OF DEVICE TEMPLATE t1 FROM root.sg1.*, root.sg2.*
2. 卸载模板(回收挂载关系)
-- 卸载root.sg1.d1下的模板t1(一定要先解除激活才能卸载)
IoTDB > UNSET DEVICE TEMPLATE t1 FROM root.sg1.d1
3. 删除模板(DROP DEVICE TEMPLATE)
-- 删除模板t1(得先把所有挂载路径下的模板都卸载了才能删)
IoTDB > DROP DEVICE TEMPLATE t1
三、时间序列管理:IoTDB 数据存储的核心单元
时间序列(Timeseries)是 IoTDB 中存储时序数据的最小单元,每个时间序列都对应着一个物理量,比如温度、湿度。这一节,咱们就详细聊聊时间序列的创建、删除、查看、统计还有标签管理这些操作。
3.1 创建时间序列(CREATE TIMESERIES)
创建时间序列的时候,得指定路径和数据类型,语法上有简化版的,也支持自己定义编码和压缩方式。
1. 基础语法(v0.13+ 支持简化版)
-- 完整版语法(得指定datatype)
IoTDB > CREATE TIMESERIES root.ln.wf01.wt01.status WITH DATATYPE=BOOLEAN
-- 简化版语法(直接指定数据类型就行,这个更推荐用)
IoTDB > CREATE TIMESERIES root.ln.wf01.wt01.status BOOLEAN
-- 自定义编码与压缩方式
IoTDB > CREATE TIMESERIES root.sgcc.wf03.wt01.temperature FLOAT encoding=PLAIN compression=SNAPPY
2. 错误示例:编码与数据类型不匹配
-- BOOLEAN类型不支持TS_2DIFF编码,这么写系统肯定会报错
IoTDB > CREATE TIMESERIES root.ln.wf02.wt02.status WITH DATATYPE=BOOLEAN, ENCODING=TS_2DIFF
-- 报错信息:error: encoding TS_2DIFF does not support BOOLEAN
3.2 创建对齐时间序列(CREATE ALIGNED TIMESERIES)
对齐时间序列特别适合多物理量同步采集的场景,比如GPS经纬度、设备上多个传感器的数据采集。它们共用一个时间戳,不管是插入数据还是查询数据,效率都更高。
核心语法与示例
-- 创建对齐时间序列:root.ln.wf01.GPS下包含latitude(FLOAT类型)和longitude(FLOAT类型)
IoTDB > CREATE ALIGNED TIMESERIES root.ln.wf01.GPS(latitude FLOAT, longitude FLOAT)
-- 自定义编码与压缩方式
IoTDB > CREATE ALIGNED TIMESERIES root.ln.wf01.GPS(
latitude FLOAT encoding=GORILLA,
longitude FLOAT encoding=GORILLA compression=SNAPPY
)
-- 为对齐序列添加标签与属性
IoTDB > CREATE ALIGNED TIMESERIES root.sg1.d1(
s1 INT32 tags(tag1=v1, tag2=v2) attributes(attr1=v1, attr2=v2),
s2 DOUBLE tags(tag3=v3, tag4=v4) attributes(attr3=v3, attr4=v4)
)
3.3 删除时间序列(DELETE / DROP TIMESERIES)
删除时间序列的时候,它下面所有的数据也会一起被删掉。不管是单条删除、多条删除,还是批量删除,都能操作。
核心语法与示例
-- 删除单条时间序列
IoTDB > DELETE TIMESERIES root.ln.wf01.wt01.status
-- 删除多条时间序列(用逗号把路径分开就行)
IoTDB > DELETE TIMESERIES root.ln.wf01.wt01.temperature, root.ln.wf02.wt02.hardware
-- 批量删除:删除root.ln.wf02下所有时间序列(*代表单层)
IoTDB > DELETE TIMESERIES root.ln.wf02.*
-- 也可以用下面这个等价的语法
IoTDB > DROP TIMESERIES root.ln.wf02.*
3.4 查看时间序列(SHOW TIMESERIES)
查看时间序列的功能很灵活,既能看所有的,也能按路径过滤,还能按条件筛选,比如包含指定字符串、特定数据类型、特定标签这些,甚至还支持分页查询。
1. 基础查看
-- 查看所有时间序列
IoTDB > SHOW TIMESERIES
-- 按路径过滤:查看root.ln下所有时间序列(**代表多层)
IoTDB > SHOW TIMESERIES root.ln.**
2. 按条件筛选
-- 1. 按时间序列名称包含某个字符串筛选(比如包含"wf01.wt")
IoTDB > SHOW TIMESERIES root.ln.** WHERE TIMESERIES contains 'wf01.wt'
-- 2. 按数据类型筛选(比如只看FLOAT类型的)
IoTDB > SHOW TIMESERIES root.ln.** WHERE DATATYPE=FLOAT
-- 3. 按标签筛选(比如标签unit='c'的)
IoTDB > SHOW TIMESERIES root.ln.** WHERE TAGS(unit)='c'
-- 4. 按标签包含某个字符串筛选(比如标签description包含"test1")
IoTDB > SHOW TIMESERIES root.ln.** WHERE TAGS(description) contains 'test1'
3. 分页查询(LIMIT / OFFSET)
-- 从第10条开始,返回10条时间序列(数据量大的时候用这个特别方便)
IoTDB > SHOW TIMESERIES root.ln.** LIMIT 10 OFFSET 10
4. 查看最新插入的时间序列(SHOW LATEST TIMESERIES)
-- 按最近插入的时间戳倒序排列,能快速看到最新加的时间序列
IoTDB > SHOW LATEST TIMESERIES root.ln.**
3.5 统计时间序列数量(COUNT TIMESERIES)
统计时间序列数量的时候,也能按路径、数据类型、标签这些条件来筛选,还能按层级(LEVEL)分组统计,特别灵活。
1. 基础统计
-- 统计所有时间序列数量
IoTDB > COUNT TIMESERIES
-- 统计root.ln下所有时间序列数量
IoTDB > COUNT TIMESERIES root.ln.**
2. 按条件统计
-- 统计名称包含"sgcc"的时间序列数量
IoTDB > COUNT TIMESERIES root.** WHERE TIMESERIES contains 'sgcc'
-- 统计INT64类型的时间序列数量
IoTDB > COUNT TIMESERIES root.** WHERE DATATYPE=INT64
-- 统计标签unit='c'的时间序列数量
IoTDB > COUNT TIMESERIES root.** WHERE TAGS(unit)='c'
3. 按层级分组统计(GROUP BY LEVEL)
在 IoTDB 里,路径层级是从 root 开始算的,root 是 LEVEL=0。用分组统计的方式,能快速看出各个层级设备的传感器数量,特别实用。
示例场景:假设有下面这些时间序列:
- root.sgcc.wf03.wt01.temperature
- root.sgcc.wf03.wt01.status
- root.turbine.d1.s1
- root.ln.wf02.wt02.hardware
- root.ln.wf02.wt02.status
- root.ln.wf01.wt01.temperature
- root.ln.wf01.wt01.status
按层级统计:
-- 按LEVEL=1分组(root的直接子节点:sgcc、turbine、ln)
IoTDB > COUNT TIMESERIES root.** GROUP BY LEVEL=1
+------------+-----------------+
| column|count(timeseries)|
+------------+-----------------+
| root.sgcc| 2| -- sgcc下有2个时间序列
|root.turbine| 1| -- turbine下有1个时间序列
| root.ln| 4| -- ln下有4个时间序列
+------------+-----------------+
-- 按LEVEL=2分组(ln的直接子节点:wf01、wf02)
IoTDB > COUNT TIMESERIES root.ln.** GROUP BY LEVEL=2
+------------+-----------------+
| column|count(timeseries)|
+------------+-----------------+
|root.ln.wf02| 2| -- wf02下有2个时间序列
|root.ln.wf01| 2| -- wf01下有2个时间序列
+------------+-----------------+
3.6 标签与属性管理:增强时间序列元数据
标签(Tags)和属性(Attributes)都是用来补充时间序列元数据信息的,但它们俩不一样,得区分清楚。
- 标签:支持反向查询,就是从标签能找到时间序列路径,而且会在内存里维护倒排索引,适合经常用来筛选的场景;
- 属性:只能正向查询,就是从时间序列路径找到属性,不维护索引,适合存一些附加信息。
1. 创建时添加标签与属性
-- 为root.turbine.d1.s1添加别名(temprature)、标签和属性
IoTDB > CREATE TIMESERIES root.turbine.d1.s1(temprature)
WITH DATATYPE=FLOAT
TAGS(tag1=v1, tag2=v2)
ATTRIBUTES(attr1=v1, attr2=v2)
- 别名:括号里的
temprature是传感器 s1 的别名,之后查询的时候,用root.turbine.d1.temprature也能找到这个时间序列。
2. 更新标签与属性
更新标签和属性的操作很丰富,重命名、修改值、删除、新增、批量更新这些都能做:
-- 1. 把标签tag1重命名为newTag1
IoTDB > ALTER TIMESERIES root.turbine.d1.s1 RENAME tag1 TO newTag1
-- 2. 修改标签newTag1和属性attr1的值
IoTDB > ALTER TIMESERIES root.turbine.d1.s1 SET newTag1=newV1, attr1=newV1
-- 3. 删除标签tag2和属性attr2
IoTDB > ALTER TIMESERIES root.turbine.d1.s1 DROP tag2, attr2
-- 4. 新增标签tag3、tag4和属性attr3、attr4
IoTDB > ALTER TIMESERIES root.turbine.d1.s1
ADD TAGS tag3=v3, tag4=v4
ADD ATTRIBUTES attr3=v3, attr4=v4
-- 5. 批量更新(要是不存在就插入,存在的话就覆盖)
IoTDB > ALTER TIMESERIES root.turbine.d1.s1
UPSERT ALIAS=newAlias
TAGS(tag2=newV2, tag3=v3)
ATTRIBUTES(attr3=v3, attr4=v4)
3. 按标签筛选查询
-- 为时间序列添加标签
IoTDB > ALTER TIMESERIES root.ln.wf02.wt02.hardware ADD TAGS unit=c
IoTDB > ALTER TIMESERIES root.ln.wf02.wt02.status ADD TAGS description=test1
-- 按标签unit='c'筛选
IoTDB > SHOW TIMESERIES root.ln.** WHERE TAGS(unit)='c'
-- 按标签description包含'test1'筛选
IoTDB > SHOW TIMESERIES root.ln.** WHERE TAGS(description) contains 'test1'
四、路径查询:定位 IoTDB 中的数据节点
路径(Path)是 IoTDB 中节点的层级表达式,还支持用通配符模糊匹配。通过路径查询,能查看子路径、子节点,统计节点数,还能查看设备信息,是定位数据节点的好帮手。
4.1 路径基础语法
| 元素 | 定义 | 示例 |
|---|---|---|
| 路径(Path) | 由.分隔的节点名组成,开头必须是root |
root.ln.wf01.wt01 |
| 节点名(NodeName) | 路径中的每一部分,支持用通配符 | wt01、*、** |
| 单层通配符(*) | 只匹配一层节点 | root.ln.*(匹配root.ln下所有直接子节点) |
| 多层通配符(**) | 能匹配一层或多层节点 | root.ln.**(匹配root.ln下所有层级节点) |
注意事项
- root 是保留字符,只能在路径开头用;
- 通配符
*和**不能放在路径开头; - Windows 系统下,路径节点名不区分大小写,比如root.ln和root.LN会被当成同一路径。
4.2 查看子路径(SHOW CHILD PATHS)
想知道指定路径模式匹配的所有路径的下一层路径,还有对应的节点类型,比如是DATABASE、DEVICE还是TIMESERIES,用 SHOW CHILD PATHS 命令就行。
核心语法与示例
-- 查看root.ln的下一层路径及节点类型
IoTDB > SHOW CHILD PATHS root.ln
+------------+----------+
| child paths|node types|
+------------+----------+
|root.ln.wf01| INTERNAL| -- 内部节点(不是终端节点)
|root.ln.wf02| INTERNAL|
+------------+----------+
-- 查看root.*.*匹配的路径的下一层路径
IoTDB > SHOW CHILD PATHS root.*.*
+---------------+
| child paths|
+---------------+
|root.ln.wf01.s1| -- 时间序列节点(终端节点)
|root.ln.wf02.s2|
+---------------+
节点类型说明
- ROOT:根节点;
- DATABASE:数据库节点;
- INTERNAL:内部节点(不是数据库、设备,也不是时间序列);
- DEVICE:设备节点;
- TIMESERIES:时间序列节点。
4.3 查看子节点(SHOW CHILD NODES)
要是只想看指定路径模式匹配的节点的下一层节点名称,不想看完整路径,那就用 SHOW CHILD NODES 命令。
核心语法与示例
-- 查看root的下一层节点
IoTDB > SHOW CHILD NODES root
+------------+
| child nodes|
+------------+
| ln|
| sgcc|
+------------+
-- 查看root.ln的下一层节点
IoTDB > SHOW CHILD NODES root.ln
+------------+
| child nodes|
+------------+
| wf01|
| wf02|
+------------+
4.4 统计节点数(COUNT NODES)
想统计指定路径模式下,特定层级的节点个数,比如统计设备数、传感器数这些,用 COUNT NODES 命令就很方便。
核心语法与示例
-- 统计root下所有层级、LEVEL=2的节点数
IoTDB > COUNT NODES root.** LEVEL=2
-- 统计root.ln下所有层级、LEVEL=2的节点数
IoTDB > COUNT NODES root.ln.** LEVEL=2
-- 统计包含temperature的路径中,LEVEL=3的节点数
IoTDB > COUNT NODES root.**.temperature LEVEL=3
执行结果示例
-- 统计root.**.temperature LEVEL=3的节点数(一共2个)
+------------+
|count(nodes)|
+------------+
| 2|
+------------+
4.5 查看设备(SHOW DEVICES)
查看设备信息的时候,能看到设备路径、是否对齐(IsAligned)、激活的模板(Template)这些。而且还能按路径模式、设备名称、模板来筛选,特别灵活。
核心语法与示例
-- 查看所有设备
IoTDB > SHOW DEVICES
-- 查看root.ln下所有设备
IoTDB > SHOW DEVICES root.ln.**
-- 按设备名称包含't'筛选
IoTDB > SHOW DEVICES root.ln.** WHERE DEVICE contains 't'
-- 按模板筛选(只看激活了模板t1的设备)
IoTDB > SHOW DEVICES root.ln.** WHERE TEMPLATE = 't1'
-- 查看设备以及它们所属的数据库
IoTDB > SHOW DEVICES WITH DATABASE
执行结果示例
-- 查看设备及所属数据库
+-------------------+-------------+---------+---------+
| devices| database|isAligned| Template|
+-------------------+-------------+---------+---------+
| root.ln.wf01.wt01| root.ln| false| t1| -- 非对齐设备,激活了模板t1
| root.ln.wf02.wt02| root.ln| false| null| -- 非对齐设备,没激活模板
|root.sgcc.wf03.wt01| root.sgcc| false| null|
+-------------------+-------------+---------+---------+
4.6 统计设备数量(COUNT DEVICES)
想知道符合指定路径模式的设备有多少个,用 COUNT DEVICES 命令很快就能得到结果。
核心语法与示例
-- 统计所有设备数量
IoTDB > COUNT DEVICES
-- 统计root.ln下的设备数量
IoTDB > COUNT DEVICES root.ln.**
执行结果示例
-- 统计root.ln下的设备数量(一共2个)
+--------------+
|count(devices)|
+--------------+
| 2|
+--------------+
五、数据写入:IoTDB 时序数据的接入方式
IoTDB 支持好几种数据写入方式,像 CLI 插入、原生接口(还支持多语言)、REST API、MQTT,还有批量导入。不管是实时写入数据,还是导入历史数据,都能找到合适的方式。
5.1 CLI 写入:快速验证数据接入
要是想快速验证数据能不能接入,直接用 CLI 工具执行 INSERT 语句就行,单条数据或者多条数据都能写。
1. 基础写入(非对齐序列)
不管是单列数据、多列数据,还是多行数据,都能插入,而且时间戳还能省略,这时候会用系统当前时间。
-- 1. 单列数据插入:向root.ln.wf02.wt02.status插入时间戳1、值true
IoTDB > INSERT INTO root.ln.wf02.wt02(timestamp, status) VALUES(1, true)
-- 2. 多列数据插入:在同一个时间戳下,插入status和hardware的值
IoTDB > INSERT INTO root.ln.wf02.wt02(timestamp, status, hardware) VALUES(2, false, 'v2')
-- 3. 多行数据插入:多个时间戳一起批量插入
IoTDB > INSERT INTO root.ln.wf02.wt02(timestamp, status, hardware) VALUES
(3, false, 'v3'),
(4, true, 'v4')
-- 4. 省略时间戳:这时候会用系统当前时间作为数据的时间戳
IoTDB > INSERT INTO root.ln.wf02.wt02(status, hardware) VALUES(false, 'v5')
2. 对齐序列写入
写入对齐序列的时候,得在 INSERT 语句里加 ALIGNED 关键字,其他语法和非对齐序列是一样的。
-- 1. 先创建对齐序列
IoTDB > CREATE ALIGNED TIMESERIES root.sg1.d1(s1 INT32, s2 DOUBLE)
-- 2. 单行写入对齐数据
IoTDB > INSERT INTO root.sg1.d1(time, s1, s2) ALIGNED VALUES(1, 1, 1.0)
-- 3. 多行写入对齐数据
IoTDB > INSERT INTO root.sg1.d1(time, s1, s2) ALIGNED VALUES
(2, 2, 2.0),
(3, 3, 3.0)
3. 写入验证(SELECT 查询)
-- 查询root.sg1.d1的所有数据,看看写进去没
IoTDB > SELECT * FROM root.sg1.d1
+-----------------------------+--------------+--------------+
| Time|root.sg1.d1.s1|root.sg1.d1.s2|
+-----------------------------+--------------+--------------+
|1970-01-01T08:00:00.001+08:00| 1| 1.0|
|1970-01-01T08:00:00.002+08:00| 2| 2.0|
|1970-01-01T08:00:00.003+08:00| 3| 3.0|
+-----------------------------+--------------+--------------+
5.2 原生接口写入:多语言高性能接入
原生接口(Session)是 IoTDB 推荐的高性能写入方式,支持 Java、Python、C++、Go 这些常用语言,在生产环境里批量写入数据的时候用它特别合适。
1. Java 原生接口示例
用 Java 原生接口写入数据,得先建立 Session 连接,然后通过 insertTablet 或者 insertRecords 来写入数据。
import org.apache.iotdb.session.Session;
import org.apache.iotdb.tsfile.write.record.Tablet;
import org.apache.iotdb.tsfile.write.schema.MeasurementSchema;
import org.apache.iotdb.tsfile.file.metadata.enums.TSDataType;
import org.apache.iotdb.tsfile.file.metadata.enums.TSEncoding;
import java.util.ArrayList;
import java.util.List;
public class IoTDBJavaWrite {
public static void main(String[] args) throws Exception {
// 1. 先建立Session连接
Session session = new Session("127.0.0.1", 6667, "root", "root");
session.open();
// 2. 定义设备路径和测量值的schema
String deviceId = "root.sg1.d1";
List<MeasurementSchema> schemas = new ArrayList<>();
schemas.add(new MeasurementSchema("s1", TSDataType.INT32, TSEncoding.RLE));
schemas.add(new MeasurementSchema("s2", TSDataType.DOUBLE, TSEncoding.GORILLA));
// 3. 构造Tablet(这是批量写入数据用的结构)
Tablet tablet = new Tablet(deviceId, schemas, 3); // 这里准备写3行数据
int row = 0;
// 第1行数据:时间戳1,s1=1,s2=1.0
tablet.addTimestamp(row, 1);
tablet.addValue("s1", row, 1);
tablet.addValue("s2", row, 1.0);
row++;
// 第2行数据:时间戳2,s1=2,s2=2.0
tablet.addTimestamp(row, 2);
tablet.addValue("s1", row, 2);
tablet.addValue("s2", row, 2.0);
row++;
// 第3行数据:时间戳3,s1=3,s2=3.0
tablet.addTimestamp(row, 3);
tablet.addValue("s1", row, 3);
tablet.addValue("s2", row, 3.0);
row++;
// 4. 写入数据
session.insertTablet(tablet);
// 5. 写完数据别忘了关闭连接
session.close();
}
}
2. Python 原生接口示例
from iotdb.Session import Session
# 1. 建立Session连接
session = Session("127.0.0.1", 6667, "root", "root")
session.open()
# 2. 定义设备路径、测量值、数据类型和要写入的数据
device_id = "root.sg1.d1"
measurements = ["s1", "s2"]
data_types = ["INT32", "DOUBLE"]
values = [
(1, 1, 1.0), # 格式是(时间戳, s1值, s2值)
(2, 2, 2.0),
(3, 3, 3.0)
]
# 3. 批量写入数据
session.insert_records(device_id, measurements, data_types, values)
# 4. 关闭连接
session.close()
5.3 REST API 写入:跨平台无依赖接入
通过 REST API 写入数据,不用依赖 IoTDB 客户端,不管是跨平台场景,还是云原生场景,用它都很方便。
核心请求参数
- URL:
http://{ip}:{port}/rest/v1/insert/tablet - Method:POST
- Content-Type:application/json
请求体示例(非对齐序列)
{
"timestamps": [1, 2, 3], // 时间戳列表
"measurements": ["temperature", "status"], // 测量值名称
"data_types": ["FLOAT", "BOOLEAN"], // 数据类型
"values": [
[1.1, 2.2, 3.3], // temperature的值列表(和timestamps是一一对应的)
[false, true, true] // status的值列表
],
"is_aligned": false, // 是不是对齐序列
"device": "root.ln.wf01.wt01" // 设备路径
}
5.4 MQTT 写入:物联网设备实时接入
IoTDB 本身就内置了 MQTT 服务,物联网设备可以直接通过 MQTT 协议写入数据,不用再额外装中间件,特别方便。
配置与写入流程
- 启用 MQTT 服务:先修改
iotdb-engine.properties文件,把enable_mqtt_service设置成true,然后配置端口(默认是1883); - 设备端发布消息:
- Topic:格式是
iotdb/{deviceId},比如iotdb/root.ln.wf01.wt01; - Payload:用 JSON 格式,里面要包含时间戳、测量值和对应的值,比如
{"timestamp":1, "measurements":["status"], "values":[true]};
- Topic:格式是
- 验证数据:用 CLI 执行
SELECT语句,看看数据有没有成功写进去。
5.5 批量导入:历史数据快速接入
要是有历史数据要导入,比如离线日志、第三方系统里的数据,IoTDB 支持 TsFile 和 CSV 这两种格式的批量导入,效率都挺高的。
1. TsFile 导入
TsFile 是 IoTDB 的原生文件格式,用它来导入数据,效率是最高的:
-- 从本地文件系统导入TsFile
IoTDB > LOAD DATA INPATH '/path/to/your/data.tsfile' INTO DATABASE root.ln
-- 从HDFS导入TsFile
IoTDB > LOAD DATA INPATH 'hdfs://localhost:9000/path/to/data.tsfile' INTO DATABASE root.ln
2. CSV 导入
CSV 文件得按照指定格式来组织,首行是测量值名称,后面每一行是时间戳和对应的值。导入的时候,系统还能自动推断数据类型,很省心。
-- 导入单个CSV文件(要指定对应的数据库)
IoTDB > IMPORT CSV FILE '/path/to/your/data.csv' INTO DATABASE root.ln
-- 导入一个文件夹下所有的CSV文件
IoTDB > IMPORT CSV FOLDER '/path/to/your/csv/folder' INTO DATABASE root.ln
CSV 文件格式示例
timestamp,status,hardware
1,true,v1
2,false,v2
3,false,v3
5.6 无模式写入:动态设备快速接入
在物联网场景里,设备的类型和数量可能会随时变化,这时候 IoTDB 的「无模式写入」就派上用场了。不用提前创建数据库、模板或者时间序列,写入数据的时候,系统会自动注册元数据,特别灵活。
示例:无模式写入数据
-- 直接写入数据,系统会自动创建数据库root.ln、设备wt01、时间序列status
IoTDB > INSERT INTO root.ln.wt01(timestamp, status) VALUES(1, true)
-- 验证一下系统自动创建的元数据
IoTDB > SHOW DATABASES -- 这里面会包含root.ln
IoTDB > SHOW DEVICES root.ln.** -- 这里面会包含root.ln.wt01
IoTDB > SHOW TIMESERIES root.ln.wt01.** -- 这里面会包含root.ln.wt01.status
六、总结与最佳实践
IoTDB 作为一款物联网时序数据库,它的核心优势就在于能高效管理和写入时序数据。结合前面讲的内容,我给大家总结几个最佳实践,帮大家在实际项目里少走弯路。
- 数据库设计:建议给每个业务场景创建一个数据库,比如root.ln对应电力场景,root.sgcc对应电网场景。别搞太多层数据库,不然管理起来会很麻烦;
- 模板复用:遇到同类型的设备,比如同一型号的传感器,优先用设备模板。这样能减少元数据冗余,管理效率也更高;
- TTL 配置:根据数据的生命周期,设置合理的 TTL。比如热数据保留1个月,冷数据保留1年,这样能避免磁盘空间被占满;
- 写入方式选择:
- 要是实时单条写入数据,用 MQTT 或者 CLI 就挺合适;
- 要是批量实时写入,Java/Python 原生接口是首选,性能好;
- 导入历史数据的话,用 TsFile 批量导入效率最高;
- 要是跨平台或者不想依赖客户端,REST API 就很方便;
- 查询优化:多利用标签筛选来缩小查询范围,用通配符
**的时候,别太模糊,比如优先用root.ln.**,别一上来就用root.**,这样能提高查询效率。
通过这篇文章的详细讲解和代码示例,相信大家已经能快速掌握 IoTDB 的核心操作了,在实际项目里应该也能灵活应用,把物联网时序数据的存储和管理工作做好。要是想更深入地学习 IoTDB,可以去看官方文档(https://iotdb.apache.org/),里面还有很多高级特性,像分区策略、查询优化、集群部署这些内容等着大家去探索。
🌐 附: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/,如果相关下载没有跳转,请查看这个地址,相关链接没有跳转,皆是抄袭本文,转载请备注本文原地址。
📣 亲,码字不易,动动小手,欢迎 点赞 ➕ 收藏,如 🈶 问题请留言(或者关注下方公众号,看见后第一时间回复,还有海量编程资料等你来领!),博主看见后一定及时给您答复 💌💌💌