Apache IoTDB(8):时间序列管理——从创建到分析的实战指南
引言:物联网时代的时序数据管理革命
Apache IoTDB作为专为物联网场景设计的时序数据库,凭借其独特的树形数据模型、高效压缩算法和边云协同架构,正在成为解决“数据爆炸式增长”与“管理效率低下”的矛盾的"数据引擎"。

Apache IoTDB 时序数据库【系列篇章】:
| No. | 文章地址(点击进入) |
|---|---|
| 1 | Apache IoTDB(1):时序数据库介绍与单机版安装部署指南 |
| 2 | Apache IoTDB(2):时序数据库 IoTDB 集群安装部署的技术优势与适用场景分析 |
| 3 | Apache IoTDB(3):时序数据库 IoTDB Docker部署从单机到集群的全场景部署与实践指南 |
| 4 | Apache IoTDB(4):深度解析时序数据库 IoTDB 在Kubernetes 集群中的部署与实践指南 |
| 5 | Apache IoTDB(5):深度解析时序数据库 IoTDB 中 AINode 工具的部署与实践 |
| 6 | Apache IoTDB(6):深入解析数据库管理操作——增删改查与异构数据库实战指南 |
| 7 | Apache IoTDB(7):设备模板管理——工业物联网元数据标准化的破局之道 |
Apache IoTDB作为专为时序数据打造的开源数据库,其时间序列管理能力堪称行业标杆。本文详细讲述时间序列管理的完整生命周期——从创建到删除,从基础操作到高级优化,构建高效、可扩展的时序数据管理体系。
一、IoTDB时间序列管理基础:为什么需要专用时序数据库?
IoTDB的时间序列管理采用“元数据-存储-查询”三级架构,每个层级都经过精心设计以适应高并发、高吞吐的工业场景。

1.1 元数据管理:Schema on Write模式
IoTDB采用预定义的元数据模式,通过Device Template和Timeseries Schema实现元数据的标准化。每个时间序列包含路径、数据类型、编码方式、压缩算法四维元信息。
这种模式确保了数据写入的规范性和查询的高效性。与传统NoSQL数据库的Schema on Read模式相比,IoTDB的元数据管理减少了运行时解析开销,写入性能提升
1.2 存储引擎:TsFile的精妙设计
TsFile作为IoTDB的专用存储格式,采用分层存储结构:
- 头部元数据区:存储时间序列的元信息
- 数据区:按时间戳排序存储实际数据
- 索引区:构建时间戳与值的双B+树索引
这种设计使得时间范围查询效率提升,空间占用减少。
1.3 内存管理:多级缓存策略
IoTDB采用三级缓存架构:
- 元数据缓存:存储最近访问的100万个时间序列元数据
- 数据缓存:采用LRU算法缓存热点数据
- 块缓存:预加载关联数据块,减少磁盘I/O
这种策略将元数据访问延迟降低
二、实操——时间序列的创建、创建对齐、删除
2.1 创建时间序列
根据建立的数据模型,我们可以分别在两个数据库中创建相应的时间序列。
第一种:创建时间序列的 SQL 语句如下所示:
IoTDB > create timeseries root.ln.wf01.wt01.status with datatype=BOOLEAN
IoTDB > create timeseries root.ln.wf01.wt01.temperature with datatype=FLOAT
IoTDB > create timeseries root.ln.wf02.wt02.hardware with datatype=TEXT
IoTDB > create timeseries root.ln.wf02.wt02.status with datatype=BOOLEAN
IoTDB > create timeseries root.sgcc.wf03.wt01.status with datatype=BOOLEAN
IoTDB > create timeseries root.sgcc.wf03.wt01.temperature with datatype=FLOAT
第二种:也可以使用简化版的 SQL 语句创建时间序列:
IoTDB > create timeseries root.ln.wf01.wt01.status BOOLEAN
IoTDB > create timeseries root.ln.wf01.wt01.temperature FLOAT
IoTDB > create timeseries root.ln.wf02.wt02.hardware TEXT
IoTDB > create timeseries root.ln.wf02.wt02.status BOOLEAN
IoTDB > create timeseries root.sgcc.wf03.wt01.status BOOLEAN
IoTDB > create timeseries root.sgcc.wf03.wt01.temperature FLOAT
创建时间序列时,系统会默认指定编码压缩方式,无需手动指定,若业务场景需要手动调整,可参考如下示例:
IoTDB > create timeseries root.sgcc.wf03.wt01.temperature FLOAT encoding=PLAIN compressor=SNAPPY
需要注意的是,如果手动指定了编码方式,但与数据类型不对应时,系统会给出相应的错误提示,如下所示:
IoTDB> create timeseries root.ln.wf02.wt02.status WITH DATATYPE=BOOLEAN, ENCODING=TS_2DIFF
error: encoding TS_2DIFF does not support BOOLEAN
2.2 创建对齐时间序列
创建一组对齐时间序列的SQL语句如下所示:
IoTDB> CREATE ALIGNED TIMESERIES root.ln.wf01.GPS(latitude FLOAT, longitude FLOAT)
一组对齐序列中的序列可以有不同的数据类型、编码方式以及压缩方式。
对齐的时间序列也支持设置别名、标签、属性。
2.3 删除时间序列
可以使用(DELETE | DROP) TimeSeries 语句来删除我们之前创建的时间序列。SQL 语句如下所示:
IoTDB> delete timeseries root.ln.wf01.wt01.status
IoTDB> delete timeseries root.ln.wf01.wt01.temperature, root.ln.wf02.wt02.hardware
IoTDB> delete timeseries root.ln.wf02.*
IoTDB> drop timeseries root.ln.wf02.*
三、实操——时间序列的查看
SHOW LATEST? TIMESERIES pathPattern? timeseriesWhereClause? limitClause?
SHOW TIMESERIES 中可以有四种可选的子句,查询结果为这些时间序列的所有信息
时间序列信息具体包括:时间序列路径名,database,Measurement 别名,数据类型,编码方式,压缩方式,属性和标签。
展示系统中所有的时间序列信息:
SHOW TIMESERIES
SHOW TIMESERIES <Path>
返回给定路径的下的所有时间序列信息。其中 Path 需要为一个时间序列路径或路径模式。例如,分别查看root路径和root.ln路径下的时间序列,SQL 语句如下所示:
IoTDB> show timeseries root.**
IoTDB> show timeseries root.ln.**
执行结果分别如下:
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
| timeseries| alias| database|dataType|encoding|compression| tags| attributes|deadband|deadband parameters|
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
|root.sgcc.wf03.wt01.temperature| null| root.sgcc| FLOAT| RLE| SNAPPY| null| null| null| null|
| root.sgcc.wf03.wt01.status| null| root.sgcc| BOOLEAN| PLAIN| SNAPPY| null| null| null| null|
| root.turbine.d1.s1|newAlias| root.turbine| FLOAT| RLE| SNAPPY|{"newTag1":"newV1","tag4":"v4","tag3":"v3"}|{"attr2":"v2","attr1":"newV1","attr4":"v4","attr3":"v3"}| null| null|
| root.ln.wf02.wt02.hardware| null| root.ln| TEXT| PLAIN| SNAPPY| null| null| null| null|
| root.ln.wf02.wt02.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY| null| null| null| null|
| root.ln.wf01.wt01.temperature| null| root.ln| FLOAT| RLE| SNAPPY| null| null| null| null|
| root.ln.wf01.wt01.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY| null| null| null| null|
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
Total line number = 7
It costs 0.016s+-----------------------------+-----+-------------+--------+--------+-----------+----+----------+--------+-------------------+
| timeseries|alias| database|dataType|encoding|compression|tags|attributes|deadband|deadband parameters|
+-----------------------------+-----+-------------+--------+--------+-----------+----+----------+--------+-------------------+
| root.ln.wf02.wt02.hardware| null| root.ln| TEXT| PLAIN| SNAPPY|null| null| null| null|
| root.ln.wf02.wt02.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY|null| null| null| null|
|root.ln.wf01.wt01.temperature| null| root.ln| FLOAT| RLE| SNAPPY|null| null| null| null|
| root.ln.wf01.wt01.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY|null| null| null| null|
+-----------------------------+-----+-------------+--------+--------+-----------+----+----------+--------+-------------------+
Total line number = 4
It costs 0.004s
SHOW TIMESERIES LIMIT INT OFFSET INT
只返回从指定下标开始的结果,最大返回条数被 LIMIT 限制,用于分页查询。例如:
show timeseries root.ln.** limit 10 offset 10
SHOW TIMESERIES WHERE TIMESERIES contains 'containStr'
对查询结果集根据 timeseries 名称进行字符串模糊匹配过滤。例如:
show timeseries root.ln.** where timeseries contains 'wf01.wt'
执行结果为:
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
| timeseries| alias| database|dataType|encoding|compression| tags| attributes|deadband|deadband parameters|
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
| root.ln.wf01.wt01.temperature| null| root.ln| FLOAT| RLE| SNAPPY| null| null| null| null|
| root.ln.wf01.wt01.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY| null| null| null| null|
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
Total line number = 2
It costs 0.016s
SHOW TIMESERIES WHERE DataType=type
对查询结果集根据时间序列数据类型进行过滤。例如:
show timeseries root.ln.** where dataType=FLOAT
执行结果为:
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
| timeseries| alias| database|dataType|encoding|compression| tags| attributes|deadband|deadband parameters|
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
|root.sgcc.wf03.wt01.temperature| null| root.sgcc| FLOAT| RLE| SNAPPY| null| null| null| null|
| root.turbine.d1.s1|newAlias| root.turbine| FLOAT| RLE| SNAPPY|{"newTag1":"newV1","tag4":"v4","tag3":"v3"}|{"attr2":"v2","attr1":"newV1","attr4":"v4","attr3":"v3"}| null| null|
| root.ln.wf01.wt01.temperature| null| root.ln| FLOAT| RLE| SNAPPY| null| null| null| null|
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
Total line number = 3
It costs 0.016s
SHOW TIMESERIES WHERE TAGS(KEY) = VALUE
SHOW TIMESERIES WHERE TAGS(KEY) CONTAINS VALUE
对查询结果集根据标签进行过滤。例如:
show timeseries root.ln.** where TAGS(unit)='c'
show timeseries root.ln.** where TAGS(description) contains 'test1'
执行结果分别为:
+--------------------------+-----+-------------+--------+--------+-----------+------------+----------+--------+-------------------+
| timeseries|alias| database|dataType|encoding|compression| tags|attributes|deadband|deadband parameters|
+--------------------------+-----+-------------+--------+--------+-----------+------------+----------+--------+-------------------+
|root.ln.wf02.wt02.hardware| null| root.ln| TEXT| PLAIN| SNAPPY|{"unit":"c"}| null| null| null|
+--------------------------+-----+-------------+--------+--------+-----------+------------+----------+--------+-------------------+
Total line number = 1
It costs 0.005s+------------------------+-----+-------------+--------+--------+-----------+-----------------------+----------+--------+-------------------+
| timeseries|alias| database|dataType|encoding|compression| tags|attributes|deadband|deadband parameters|
+------------------------+-----+-------------+--------+--------+-----------+-----------------------+----------+--------+-------------------+
|root.ln.wf02.wt02.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY|{"description":"test1"}| null| null| null|
+------------------------+-----+-------------+--------+--------+-----------+-----------------------+----------+--------+-------------------+
Total line number = 1
It costs 0.004s
SHOW LATEST TIMESERIES
表示查询出的时间序列需要按照最近插入时间戳降序排列
需要注意的是,当查询路径不存在时,系统会返回 0 条时间序列
四、实操——统计时间序列总数
IoTDB 支持使用COUNT TIMESERIES
SQL 语句如下所示:
- 可以通过 WHERE 条件对时间序列名称进行字符串模糊匹配
语法为:COUNT TIMESERIES <Path> WHERE TIMESERIES contains 'containStr' - 可以通过 WHERE 条件对时间序列数据类型进行过滤
语法为:COUNT TIMESERIES <Path> WHERE DataType=<DataType>' - 可以通过 WHERE 条件对标签点进行过滤
语法为:COUNT TIMESERIES <Path> WHERE TAGS(key)='value' 或 COUNT TIMESERIES <Path> WHERE TAGS(key) contains 'value' - 可以通过定义LEVEL来统计指定层级下的时间序列个数。这条语句可以用来统计每一个设备下的传感器数量
语法为:COUNT TIMESERIES <Path> GROUP BY LEVEL=<INTEGER>
IoTDB > COUNT TIMESERIES root.**
IoTDB > COUNT TIMESERIES root.ln.**
IoTDB > COUNT TIMESERIES root.ln.*.*.status
IoTDB > COUNT TIMESERIES root.ln.wf01.wt01.status
IoTDB > COUNT TIMESERIES root.** WHERE TIMESERIES contains 'sgcc'
IoTDB > COUNT TIMESERIES root.** WHERE DATATYPE = INT64
IoTDB > COUNT TIMESERIES root.** WHERE TAGS(unit) contains 'c'
IoTDB > COUNT TIMESERIES root.** WHERE TAGS(unit) = 'c'
IoTDB > COUNT TIMESERIES root.** WHERE TIMESERIES contains 'sgcc' group by level = 1
例如有如下时间序列(可以使用show timeseries展示所有时间序列):
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
| timeseries| alias| database|dataType|encoding|compression| tags| attributes|deadband|deadband parameters|
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
|root.sgcc.wf03.wt01.temperature| null| root.sgcc| FLOAT| RLE| SNAPPY| null| null| null| null|
| root.sgcc.wf03.wt01.status| null| root.sgcc| BOOLEAN| PLAIN| SNAPPY| null| null| null| null|
| root.turbine.d1.s1|newAlias| root.turbine| FLOAT| RLE| SNAPPY|{"newTag1":"newV1","tag4":"v4","tag3":"v3"}|{"attr2":"v2","attr1":"newV1","attr4":"v4","attr3":"v3"}| null| null|
| root.ln.wf02.wt02.hardware| null| root.ln| TEXT| PLAIN| SNAPPY| {"unit":"c"}| null| null| null|
| root.ln.wf02.wt02.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY| {"description":"test1"}| null| null| null|
| root.ln.wf01.wt01.temperature| null| root.ln| FLOAT| RLE| SNAPPY| null| null| null| null|
| root.ln.wf01.wt01.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY| null| null| null| null|
+-------------------------------+--------+-------------+--------+--------+-----------+-------------------------------------------+--------------------------------------------------------+--------+-------------------+
Total line number = 7
It costs 0.004s
Metadata Tree 如下

可以看到,root被定义为LEVEL=0。那么当你输入如下语句时:
IoTDB > COUNT TIMESERIES root.** GROUP BY LEVEL=1
IoTDB > COUNT TIMESERIES root.ln.** GROUP BY LEVEL=2
IoTDB > COUNT TIMESERIES root.ln.wf01.* GROUP BY LEVEL=2
得到以下结果:
IoTDB> COUNT TIMESERIES root.** GROUP BY LEVEL=1
+------------+-----------------+
| column|count(timeseries)|
+------------+-----------------+
| root.sgcc| 2|
|root.turbine| 1|
| root.ln| 4|
+------------+-----------------+
Total line number = 3
It costs 0.002sIoTDB > COUNT TIMESERIES root.ln.** GROUP BY LEVEL=2
+------------+-----------------+
| column|count(timeseries)|
+------------+-----------------+
|root.ln.wf02| 2|
|root.ln.wf01| 2|
+------------+-----------------+
Total line number = 2
It costs 0.002sIoTDB > COUNT TIMESERIES root.ln.wf01.* GROUP BY LEVEL=2
+------------+-----------------+
| column|count(timeseries)|
+------------+-----------------+
|root.ln.wf01| 2|
+------------+-----------------+
Total line number = 1
It costs 0.002s
注意:时间序列的路径只是过滤条件,与 level 的定义无关
五、实操——标签点管理
可以在创建时间序列的时候,为它添加别名和额外的标签和属性信息。
5.1 标签和属性的区别
- 标签可以用来查询时间序列路径,会在内存中维护标点到时间序列路径的倒排索引:标签 -> 时间序列路径
- 属性只能用时间序列路径来查询:时间序列路径 -> 属性
所用到的扩展的创建时间序列的 SQL 语句如下所示:
create timeseries root.turbine.d1.s1(temprature) with datatype=FLOAT tags(tag1=v1, tag2=v2) attributes(attr1=v1, attr2=v2)
括号里的temprature是s1这个传感器的别名。
我们可以在任何用到s1的地方,将其用temprature代替,这两者是等价的。
注意:额外的标签和属性信息总的大小不能超过tag_attribute_total_size.
5.2 标签点属性更新
创建时间序列后,我们也可以对其原有的标签点属性进行更新,主要有以下更新方式:
- 重命名标签或属性
ALTER timeseries root.turbine.d1.s1 RENAME tag1 TO newTag1
- 重新设置标签或属性的值
ALTER timeseries root.turbine.d1.s1 SET newTag1=newV1, attr1=newV1
- 删除已经存在的标签或属性
ALTER timeseries root.turbine.d1.s1 DROP tag1, tag2
- 添加新的标签
ALTER timeseries root.turbine.d1.s1 ADD TAGS tag3=v3, tag4=v4
- 添加新的属性
ALTER timeseries root.turbine.d1.s1 ADD ATTRIBUTES attr3=v3, attr4=v4
- 更新插入别名,标签和属性
如果该别名,标签或属性原来不存在,则插入,否则,用新值更新原来的旧值
ALTER timeseries root.turbine.d1.s1 UPSERT ALIAS=newAlias TAGS(tag2=newV2, tag3=v3) ATTRIBUTES(attr3=v3, attr4=v4)
5.3 查询时间序列
使用标签作为过滤条件查询时间序列,使用 TAGS(tagKey) 来标识作为过滤条件的标签
SHOW TIMESERIES (<`PathPattern`>)? timeseriesWhereClause
返回给定路径的下的所有满足条件的时间序列信息,SQL 语句如下所示:
ALTER timeseries root.ln.wf02.wt02.hardware ADD TAGS unit=c
ALTER timeseries root.ln.wf02.wt02.status ADD TAGS description=test1
show timeseries root.ln.** where TAGS(unit)='c'
show timeseries root.ln.** where TAGS(description) contains 'test1'
执行结果分别为:
+--------------------------+-----+-------------+--------+--------+-----------+------------+----------+--------+-------------------+
| timeseries|alias| database|dataType|encoding|compression| tags|attributes|deadband|deadband parameters|
+--------------------------+-----+-------------+--------+--------+-----------+------------+----------+--------+-------------------+
|root.ln.wf02.wt02.hardware| null| root.ln| TEXT| PLAIN| SNAPPY|{"unit":"c"}| null| null| null|
+--------------------------+-----+-------------+--------+--------+-----------+------------+----------+--------+-------------------+
Total line number = 1
It costs 0.005s+------------------------+-----+-------------+--------+--------+-----------+-----------------------+----------+--------+-------------------+
| timeseries|alias| database|dataType|encoding|compression| tags|attributes|deadband|deadband parameters|
+------------------------+-----+-------------+--------+--------+-----------+-----------------------+----------+--------+-------------------+
|root.ln.wf02.wt02.status| null| root.ln| BOOLEAN| PLAIN| SNAPPY|{"description":"test1"}| null| null| null|
+------------------------+-----+-------------+--------+--------+-----------+-----------------------+----------+--------+-------------------+
Total line number = 1
It costs 0.004s
5.4 使用标签作为过滤条件统计时间序列数量
COUNT TIMESERIES (<`PathPattern`>)? timeseriesWhereClause
COUNT TIMESERIES (<`PathPattern`>)? timeseriesWhereClause GROUP BY LEVEL=<INTEGER>
返回给定路径的下的所有满足条件的时间序列的数量
SQL 语句如下所示:
count timeseries
count timeseries root.** where TAGS(unit)='c'
count timeseries root.** where TAGS(unit)='c' group by level = 2
执行结果分别为:
IoTDB> count timeseries
+-----------------+
|count(timeseries)|
+-----------------+
| 6|
+-----------------+
Total line number = 1
It costs 0.019s
IoTDB> count timeseries root.** where TAGS(unit)='c'
+-----------------+
|count(timeseries)|
+-----------------+
| 2|
+-----------------+
Total line number = 1
It costs 0.020s
IoTDB> count timeseries root.** where TAGS(unit)='c' group by level = 2
+--------------+-----------------+
| column|count(timeseries)|
+--------------+-----------------+
| root.ln.wf02| 2|
| root.ln.wf01| 0|
|root.sgcc.wf03| 0|
+--------------+-----------------+
Total line number = 3
It costs 0.011s
5.5 创建对齐时间序列
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))
执行结果如下:
IoTDB> show timeseries
+--------------+-----+-------------+--------+--------+-----------+-------------------------+---------------------------+--------+-------------------+
| timeseries|alias| database|dataType|encoding|compression| tags| attributes|deadband|deadband parameters|
+--------------+-----+-------------+--------+--------+-----------+-------------------------+---------------------------+--------+-------------------+
|root.sg1.d1.s1| null| root.sg1| INT32| RLE| SNAPPY|{"tag1":"v1","tag2":"v2"}|{"attr2":"v2","attr1":"v1"}| null| null|
|root.sg1.d1.s2| null| root.sg1| DOUBLE| GORILLA| SNAPPY|{"tag4":"v4","tag3":"v3"}|{"attr4":"v4","attr3":"v3"}| null| null|
+--------------+-----+-------------+--------+--------+-----------+-------------------------+---------------------------+--------+-------------------+
支持查询:
IoTDB> show timeseries where TAGS(tag1)='v1'
+--------------+-----+-------------+--------+--------+-----------+-------------------------+---------------------------+--------+-------------------+
| timeseries|alias| database|dataType|encoding|compression| tags| attributes|deadband|deadband parameters|
+--------------+-----+-------------+--------+--------+-----------+-------------------------+---------------------------+--------+-------------------+
|root.sg1.d1.s1| null| root.sg1| INT32| RLE| SNAPPY|{"tag1":"v1","tag2":"v2"}|{"attr2":"v2","attr1":"v1"}| null| null|
+--------------+-----+-------------+--------+--------+-----------+-------------------------+---------------------------+--------+-------------------+
结语:时间序列管理的艺术
时间序列管理不仅是技术问题,更是管理思维的革新。通过“创建-查询-统计-优化”的四步曲,IoTDB实现了从数据采集到价值挖掘的完整闭环。这种管理艺术带来的不仅是存储空间降低、查询性能提升,更是构建了可扩展、易维护的时序数据治理体系。
Apache IoTDB的时间序列管理技术,正在为物联网平台的大规模落地铺就坚实的数据基石。未来,随着自动优化、流处理等创新功能的引入,时间序列管理必将释放更大的技术价值,推动工业物联网迈向更智能、更高效的未来。
