暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

国产时序数据库IoTDB调研实践归纳

原创 大数据模型 2024-06-10
281

IoTDB简介

IoTDB 是一款国产自研的物联网原生时序数据库,其技术发源于清华大学,目前已历经 13 年的发展。IoTDB 的诞生,主要是为了解决工业物联网时序数据管理的实时性、压缩比、分布式部署等多方面痛点。

IoTDB具有以下特点:

  • 灵活的部署方式
    • 云端一键部署
    • 终端解压即用
    • 终端-云端无缝连接(数据云端同步工具)
  • 低硬件成本的存储解决方案
    • 高压缩比的磁盘存储(10 亿数据点硬盘成本低于 1.4 元)
  • 目录结构的时间序列组织管理方式
    • 支持复杂结构的智能网联设备的时间序列组织
    • 支持大量同类物联网设备的时间序列组织
    • 可用模糊方式对海量复杂的时间序列目录结构进行检索
  • 高通量的时间序列数据读写
    • 支持百万级低功耗强连接设备数据接入(海量)
    • 支持智能网联设备数据高速读写(高速)
    • 以及同时具备上述特点的混合负载
  • 面向时间序列的丰富查询语义
    • 跨设备、跨传感器的时间序列时间对齐
    • 面向时序数据特征的计算
    • 提供面向时间维度的丰富聚合函数支持
  • 极低的学习门槛
    • 支持类 SQL 的数据操作
    • 提供 JDBC 的编程接口
    • 完善的导入导出工具
  • 完美对接开源生态环境
    • 支持开源数据分析生态系统:Hadoop、Spark
    • 支持开源可视化工具对接:Grafana

IoTDB系统架构

image.png

  • 会话层: 主要提供入口对接各种应用,以及终端用户通过 应用接口发出的事务请求或各种查询要求等。支持各类的语言越多越丰富越好,IoTDB 目前支持 Java原生接口、python、C++、Go、C#、Node.js、Rust、MQTT、Kafka、REST api v1、REST api v2。

  • 处理层: 与主流分布式数据库一样, IoTDB基于LSMtree的架构进行设计,数据分为两部分,一个增量数据,一个基线数据,数据达到一定的阀值会一次性提交,存储到硬盘里面。为了数据不丢失,数据会优先写入到wal日志里面,WAL日志、memtable、sstable三者会持续协同。

    LSM 由两部分构成: 顺序数据文件空间和乱序数据文件空间。其中乱序数据文件空与LSM 中的L,层级类似,文件间的数据不存在偏序关系;而顺序数据文件空间内的多个文保持了数据在时间戳上的偏序关系,从而大幅度加速时间范围 查询操作,并避免了无效的LSM写放大。

    针对存储层的TsFile文件,IoTDB 采用了向量化的数据访问方式。

  • 存储层: IoTDB 采用列式文件结构作为数据文件格式,简称TsFile,目前支持hdfs和本地文件系统两种形式。TsFile包括数据区和索引区两部分。在数据区,单个数据序列形成多个数据块,相关序列的多数据块形成数据组。每个数据块又进一步根据操作系统的粒度分为多个数据页。

    为了加速度数据访问,每个数据页、数据头又设计了数据段头信息,用于记录该数据页(块)的统计信息,如时间范围、值范围等。

    在索引区,TsFile引入了数据组-数据块两级多层索引结构替代其它列式文件的一维数组查找表结构,将数据块定位时间 复杂度降低

IoTDB逻辑架构

从数据库视角来看,IoTDB数据库对象可以理解StorageGroup、Device、Measurement、TimeSeries。

与传统的关系数据库比较 ,StorageGroup相当于database,Device相当于表,Measurement相当于字段,TimeSeries相当于索引database+Device+Measurement+TimeSeries 确定唯一的数值。

  • StorageGroup,从用户角度,主要用于对设备数据进行分组管理;从IoTDB数据库角度,存储组又是一个并发控制和磁盘隔离的单位,不同存储组之间可以并行读写。
  • Device,对应现实世界中的具体物理设备,例如:电厂某制造单元、风力发电机、汽车、飞机发动机、地震波采集仪器等。在IoTDB中, device是时序数据一次写入的单位,一次写入请求局限在一个设备中。
  • Measurement,对应现实世界中的具体物理设备自身携带的传感器,例如:风力发电机设备上的风速、转向角、发电量等信息采集的传感器。在IoTDB中,Sensor也称为测点(Measurement),具体指传感器采集的某时刻的传感器值,在IoTDB内部采用<time, value>的形式进行列式存储。
  • TimeSeries,如其名,对应现实世界的微时间,至少是毫秒级

image.png
逻辑视角上以root为根层一级,往下划分是二级StorageGroup存储组/数据库 ,对应软件系统使用资源管理入口,第三级是物联网设备的划分,这里可以被管理的物联网设备,第四级是物联网设备的参数属性。

举例,我们对压力设备和温度设备采集数据。那么我们可以创建两个设备。

#创建压力设备,temperature做存储组 IoTDB> create DATABASE root.temperature; Msg: The statement is executed successfully. # 创建设备device1属性type1,数据类型选择text IoTDB> CREATE TIMESERIES root.temperature.device1.type1 WITH DATATYPE=text, ENCODING=PLAIN; Msg: The statement is executed successfully. # 创建设备device1属性content,数据类型选择float IoTDB> CREATE TIMESERIES root.temperature.device1.content WITH DATATYPE=FLOAT, ENCODING=PLAIN; Msg: The statement is executed successfully. #创建压力设备,ln2做存储组,设备名press IoTDB> create database root.press; Msg: The statement is executed successfully. # 创建设备device2属性type1,数据类型选择text IoTDB> CREATE TIMESERIES root.press.device2.type1 WITH DATATYPE=text, ENCODING=PLAIN; Msg: The statement is executed successfully. # 创建设备device2属性content,数据类型选择float IoTDB > insert into root.temperature.device1.content(timestamp,type1, content) VALUES (1,'name1',0.0001),(2,'name', 0.00002) # 插入多条数据 IoTDB> insert into root.temperature.device1(timestamp,type1, content) VALUES (1,'name1',0.0001),(2,'name', 0.00002) Msg: The statement is executed successfully. # 查询数据 IoTDB> select * from root.temperature.device1; +-----------------------------+------------------------------+--------------------------------+ | Time|root.temperature.device1.type1|root.temperature.device1.content| +-----------------------------+------------------------------+--------------------------------+ |1970-01-01T08:00:00.001+08:00| name1| 1.0E-4| |1970-01-01T08:00:00.002+08:00| name| 2.0E-5| +-----------------------------+------------------------------+--------------------------------+ Total line number = 2 It costs 0.367s

IoTDB物理架构

从系统视角来看,IoTDB数据库有日志文件 、配置文件、数据文件、预写文件

  • 日志文件包括confignode、datenode、
  • 配置文件包括iotdb-cluster.properties、iotdb-common.properties、iotdb-confignode.properties、iotdb-datenode.properties。
  • 数据文件是数据处理成功刷新到硬盘的数据文件。
  • 预写文件优先写入硬盘,假如意外宕机从硬盘里恢复。

image.png

image.png

IoTDB快速安装

下载介质

wget https://dlcdn.apache.org/iotdb/1.3.1/apache-iotdb-1.3.1-all-bin.zip --no-check-certificate

解压,进入路径,启动服务

bash sbin/start-standalone.sh

命令行登录ioTDB

bash sbin/start-cli.sh -h 127.0.0.1 -p 6667 -u root -pw root --------------------- Starting IoTDB Cli --------------------- _____ _________ ______ ______ |_ _| | _ _ ||_ _ `.|_ _ \ | | .--.|_/ | | \_| | | `. \ | |_) | | | / .'`\ \ | | | | | | | __'. _| |_| \__. | _| |_ _| |_.' /_| |__) | |_____|'.__.' |_____| |______.'|_______/ version 1.3.1 (Build: 214695d) Successfully login at 127.0.0.1:6667 IoTDB>

IoTDB实践使用

日常使用操作

数据库管理

数据库(Database)类似关系数据库中的 Database,是一组结构化的时序数据的集合。

  • 创建数据库

创建一个名为 root.ln 的数据库,语法如下:

CREATE DATABASE root.ln
  • 查看数据库

查看所有数据库:

SHOW DATABASES
  • 删除数据库

删除名为 root.ln 的数据库:

DELETE DATABASE root.ln
  • 统计数据库数量

统计数据库的总数

COUNT DATABASES
时间序列管理

时间序列(Timeseries)是以时间为索引的数据点的集合,在IoTDB中时间序列指的是一个测点的完整序列,本节主要介绍时间序列的管理方式。

  • 创建时间序列

需指定编码方式与数据类型。例如创建一条名为root.ln.wf01.wt01.temperature的时间序列:

CREATE TIMESERIES root.ln.wf01.wt01.temperature WITH datatype=FLOAT,ENCODING=RLE
  • 查看时间序列

查看所有时间序列:

SHOW TIMESERIES

使用通配符匹配数据库root.ln下的时间序列:

SHOW TIMESERIES root.ln.**
  • 删除时间序列

删除名为 root.ln.wf01.wt01.temperature 的时间序列

DELETE TIMESERIES root.ln.wf01.wt01.temperature
  • 统计时间序列

统计时间序列的总数

COUNT TIMESERIES root.**

统计某通配符路径下的时间序列数量:

COUNT TIMESERIES root.ln.**
时间序列路径管理

除时间序列概念外,IoTDB中还有子路径、设备的概念。

**子路径:**是一条完整时间序列名称中的一部分路径,如时间序列名称为root.ln.wf01.wt01.temperature,则root.ln、root.ln.wf01、root.ln.wf01.wt01都是其子路径。

**设备:**是一组时间序列的组合,在 IoTDB 中设备是由root至倒数第二级节点的子路径,如时间序列名称为root.ln.wf01.wt01.temperature,则root.ln.wf01.wt01是其设备

  • 查看设备
SHOW DEVICES
  • 查看子路径

查看 root.ln 的下一层:

SHOW CHILD PATHS root.ln
  • 查看子节点

查看 root.ln 的下一层:

SHOW CHILD NODES root.ln
  • 统计设备数量

统计所有设备

COUNT DEVICES
  • 统计节点数

统计路径中指定层级的节点个数

COUNT NODES root.ln.** LEVEL=2

以下为IoTDB中常用查询语句。

  • 查询指定时间序列的数据

查询root.ln.wf01.wt01设备下的所有时间序列的数据

SELECT * FROM root.ln.wf01.wt01
  • 查询某时间范围内的时间序列数据

查询root.ln.wf01.wt01.temperature时间序列中时间戳大于 2022-01-01T00:05:00.000 的数据

SELECT temperature FROM root.ln.wf01.wt01 WHERE time > 2022-01-01T00:05:00.000
  • 查询数值在指定范围内的时间序列数据

查询root.ln.wf01.wt01.temperature时间序列中数值大于 36.5 的数据:

SELECT temperature FROM root.ln.wf01.wt01 WHERE temperature > 36.5
  • 使用 last 查询最新点数据
SELECT last * FROM root.ln.wf01.wt01

时间区域查询

根据一个时间区间选择一列数据
IoTDB> select type, price from root.test.henley where time < 2024-02-18T13:12:38.001+08:00 limit 5; +-----------------------------+---------------------+----------------------+ | Time|root.test.henley.type|root.test.henley.price| +-----------------------------+---------------------+----------------------+ |2024-02-18T01:02:00.000+08:00| vechile| 0.46630436| |2024-02-18T01:02:00.001+08:00| cow| 0.69674313| |2024-02-18T01:02:00.002+08:00| phone| 0.11488286| |2024-02-18T01:02:00.003+08:00| house| 0.3449425| |2024-02-18T01:02:00.004+08:00| vechile| 0.88166314| +-----------------------------+---------------------+----------------------+ Total line number = 5 It costs 0.470s
根据一个时间区间选择多列数据
IoTDB> select type, price  from root.test.henley    where time > 2024-02-18T13:12:38.001+08:00 and  time < 2024-02-18T13:12:38.10+08:00
+-----------------------------+---------------------+----------------------+
|                         Time|root.test.henley.type|root.test.henley.price|
+-----------------------------+---------------------+----------------------+
|2024-02-18T13:12:38.002+08:00|                  car|            0.27619043|
+-----------------------------+---------------------+----------------------+
Total line number = 1
It costs 0.044s

按照多个时间区间选择同一设备的多列数据
IoTDB> select type, price from root.test.henley where (time > 2024-02-18T13:12:38.001+08:00 and time < 2024-02-18T13:12:38.10+08:00) or (time = 2024-02-18T13:12:38.001+08:00); +-----------------------------+---------------------+----------------------+ | Time|root.test.henley.type|root.test.henley.price| +-----------------------------+---------------------+----------------------+ |2024-02-18T13:12:38.001+08:00| fish| 0.101163946| |2024-02-18T13:12:38.002+08:00| car| 0.27619043| +-----------------------------+---------------------+----------------------+ Total line number = 2 It costs 2.486s
按照多个时间区间选择不同设备的多列数据
IoTDB> select henley.type, henley2.price from root.test where (time > 2024-02-18T13:12:38.001+08:00 and time < 2024-02-18T13:12:38.10+08:00) or (time = 2024-02-18T13:12:38.001+08:00);
+-----------------------------+---------------------+-----------------------+
|                         Time|root.test.henley.type|root.test.henley2.price|
+-----------------------------+---------------------+-----------------------+
|2024-02-18T13:12:38.001+08:00|                 fish|                   null|
|2024-02-18T13:12:38.002+08:00|                  car|                   null|
+-----------------------------+---------------------+-----------------------+
Total line number = 2
It costs 0.079s
按照粒度时间去进行查询

在 IoTDB 中,聚合查询可以通过 GROUP BY 子句指定按照时间区间分段聚合。用户可以指定聚合的时间间隔和滑动步长,相关参数如下:

  • 参数 1:时间轴显示时间窗口大小
  • 参数 2:聚合窗口的大小(必须为正数)
  • 参数 3:聚合窗口的滑动步长(可选,默认与聚合窗口大小相同)
#时间区域范围按照1天来进行分组排序 IoTDB> select count(type), max_value(price) from root.test.henley group by ([2024-02-18T03:12:38.001+08:00, 2024-02-25T03:12:38.001+08:00),1d); +-----------------------------+----------------------------+---------------------------------+ | Time|count(root.test.henley.type)|max_value(root.test.henley.price)| +-----------------------------+----------------------------+---------------------------------+ |2024-02-18T03:12:38.001+08:00| 660002| 0.99999964| |2024-02-19T03:12:38.001+08:00| 540000| 0.99999964| |2024-02-20T03:12:38.001+08:00| 0| null| |2024-02-21T03:12:38.001+08:00| 0| null| |2024-02-22T03:12:38.001+08:00| 0| null| |2024-02-23T03:12:38.001+08:00| 0| null| |2024-02-24T03:12:38.001+08:00| 0| null| +-----------------------------+----------------------------+---------------------------------+ Total line number = 7 It costs 48.368s

时间区域范围按照1个小时来进行分组排序

![image-20240605172657335](D:\Program Files (x86)\typoraimg\image-20240605172657335.png)

丰富的UDF函数

当前IoTDB支持数据画像、数据质量、数据修复、数据匹配、异常检测、频域相关、序列发现、字符串处理、数据平滑、数据预测、复杂事件处理,而且UDF方面编程简单方便。

#下载UDF库函数 wget https://dlcdn.apache.org/iotdb/1.3.1/apache-iotdb-1.3.1-library-udf-bin.zip --no-check-certificate #解压,将library-udf.jar 放在 lib目录下 cp library-udf.jar [lib]目录 # 重启服务,执行register-UDF.sh,显示以下信息,则是加载UDF函数成功

image.png

Completeness

本函数用于计算时间序列的完整性。将输入序列划分为若干个连续且不重叠的窗口,分别计算每一个窗口的完整性,并输出窗口第一个数据点的时间戳和窗口的完整性。

IoTDB> select completeness(price)  from root.test.henley    where time < 2024-02-18T13:12:38.001+08:00;
+-----------------------------+------------------------------------+
|                         Time|completeness(root.test.henley.price)|
+-----------------------------+------------------------------------+
|2024-02-18T01:02:00.000+08:00|                                 1.0|
+-----------------------------+------------------------------------+
Total line number = 1
It costs 15.746s

consistency

本函数用于计算时间序列的一致性。将输入序列划分为若干个连续且不重叠的窗口,分别计算每一个窗口的一致性,并输出窗口第一个数据点的时间戳和窗口的时效性。

IoTDB> select consistency(price)  from root.test.henley    where time < 2024-02-18T13:12:38.001+08:00;
+-----------------------------+-----------------------------------+
|                         Time|consistency(root.test.henley.price)|
+-----------------------------+-----------------------------------+
|2024-02-18T01:02:00.000+08:00|                                1.0|
+-----------------------------+-----------------------------------+
Total line number = 1
It costs 9.989s

Timeliness

本函数用于计算时间序列的时效性。将输入序列划分为若干个连续且不重叠的窗口,分别计算每一个窗口的时效性,并输出窗口第一个数据点的时间戳和窗口的时效性。

IoTDB> select timeliness(price) from root.test.henley where time < 2024-02-18T13:12:38.001+08:00; +-----------------------------+----------------------------------+ | Time|timeliness(root.test.henley.price)| +-----------------------------+----------------------------------+ |2024-02-18T01:02:00.000+08:00| 1.0| +-----------------------------+----------------------------------+ Total line number = 1 It costs 15.647s
validity

本函数用于计算时间序列的有效性。将输入序列划分为若干个连续且不重叠的窗口,分别计算每一个窗口的有效性,并输出窗口第一个数据点的时间戳和窗口的有效性。

IoTDB> select validity(price)  from root.test.henley    where time < 2024-02-18T13:12:38.001+08:00;
+-----------------------------+--------------------------------+
|                         Time|validity(root.test.henley.price)|
+-----------------------------+--------------------------------+
|2024-02-18T01:02:00.000+08:00|                             1.0|
+-----------------------------+--------------------------------+
Total line number = 1
It costs 7.521s

acf

本函数用于计算时间序列的自相关函数值,即序列与自身之间的互相关函数。

IoTDB> select acf(price)  from root.test.henley    where time < 2024-02-18T01:02:38.049+08:00;
+-----------------------------+---------------------------+
|                         Time|acf(root.test.henley.price)|
+-----------------------------+---------------------------+
|1970-01-01T08:00:00.000+08:00|        0.14461020512981726|
|1970-01-01T08:00:00.001+08:00|        0.13553804600169284|
|1970-01-01T08:00:00.002+08:00|         0.0947468206136044|
|1970-01-01T08:00:00.003+08:00|        0.20825145906384496|
|1970-01-01T08:00:00.004+08:00|        0.28996475874840943|
|1970-01-01T08:00:00.005+08:00|        0.22495094075784908|
|1970-01-01T08:00:00.006+08:00|        0.24271618683460874|
|1970-01-01T08:00:00.007+08:00|        0.27530544591467687|
|1970-01-01T08:00:00.008+08:00|         0.2689517084449265|
|1970-01-01T08:00:00.009+08:00|        0.28108957034799975|
|1970-01-01T08:00:00.010+08:00|        0.30070293505366075|
|1970-01-01T08:00:00.011+08:00|         0.3288760446517543|
|1970-01-01T08:00:00.012+08:00|        0.28584150978793116|
|1970-01-01T08:00:00.013+08:00|         0.3271759293151227|
|1970-01-01T08:00:00.014+08:00|         0.3296294811555682|
|1970-01-01T08:00:00.015+08:00|         0.3486298432996775|
|1970-01-01T08:00:00.016+08:00|        0.38040896181043987|
|1970-01-01T08:00:00.017+08:00|         0.3403809709060194|
|1970-01-01T08:00:00.018+08:00|        0.36407499024000656|
|1970-01-01T08:00:00.019+08:00|          0.350659235959142|

IoTDB的UDF函数很丰富

image.png

总结

  • IoTDB 是一款国人自主研发可控,并且有自主发展技术路径的数据库,具有单机布署和分布式部署多种形态
  • IoTDB的系统架构健全,在生态上与hadoop结构有广泛的生态兼容合作
  • IoTDB的存储组织与传统关系型数据差不多,这个意味着学习成本不会很高。
  • IoTDB 的可用性较高,无论是安装还是使用,都可以快速上手。
  • UDF函数是IoTDB 的灵魂,因为里面包含很多与时序相关的操作函数,在时序业务场景,可以快速投入使用。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论