IoTDB概述
什么是IoTDB
IoTDB是针对时间序列数据收集、存储与分析一体化的数据管理引擎。它具有体量轻、性能高、易使用的特点,
完美对接Hadoop与Spark生态,适用于工业物联网应用中海量时间序列数据高速写入和复杂分析查询的需求。凭借其轻巧的结构,高性能和可用功能以及与Hadoop和Spark生态的紧密集成,IoTDB满足了IoT工业领域中海量数据集存储,高速数据写入和复杂数据分析的要求。
架构
IoTDB套件由若干个组件构成,共同形成“数据收集-数据写入-数据存储-数据查询-数据可视化-数据分析”等一系列功能。
用户可以通过JDBC将来自设备上传感器采集的时序数据、服务器负载和CPU内存等系统状态数据、消息队列中
的时序数据、应用程序的时序数据或者其他数据库中的时序数据导入到本地或者远程的IoTDB中。用户还可以
将上述数据直接写成本地(或位于HDFS上)的TsFile文件。
对于写入到IoTDB的数据以及本地的TsFile文件,可以通过同步工具TsFileSync将数据文件同步到HDFS上,
进而实现在Hadoop或Spark的数据处理平台上的诸如异常检测、机器学习等数据处理任务。对于分析的结果,
可以写回成TsFile文件。
IoTDB和TsFile还提供了相应的客户端工具,满足用户查看和写入数据的SQL形式、脚本形式和图形化形式等
多种需求。
应用场景
待添加
主要功能与特点
- 灵活的部署方式
- 云端一键部署
- 终端解压即用
- 终端-云端无缝连接(数据云端同步工具)
- 低硬件成本的存储解决方案
- 高压缩比的磁盘存储(10亿数据点硬盘成本低于1.4元)
- 目录结构的时间序列组织管理方式
- 支持复杂结构的智能网联设备的时间序列组织
- 支持大量同类物联网设备的时间序列组织
- 可用模糊方式对海量复杂的时间序列目录结构进行检索
- 高通量的时间序列数据读写
- 支持百万级低功耗强连接设备数据接入(海量)
- 支持智能网联设备数据高速读写(高速)
- 以及同时具备上述特点的混合负载
- 面向时间序列的丰富查询语义
- 跨设备、跨传感器的时间序列时间对齐
- 面向时序数据特征的计算
- 提供面向时间维度的丰富聚合函数支持
- 极低的学习门槛
- 支持类SQL的数据操作
- 提供JDBC的编程接口
- 完善的导入导出工具
- 完美对接开源生态环境
- 支持开源数据分析生态系统:Hadoop、Spark
- 支持开源可视化工具对接:Grafana
IoTDB基本概念
数据模型与技术
简化的数据样例
set storage group to root.ln
create timeseries root.ln.wf01.wt01.status with datatype=BOOLEAN,encoding=PLAIN
insert into root.ln.wf01.wt01(timestamp,status) values(1509465600000,true)
insert into root.ln.wf01.wt01(timestamp,status) values(1509465780000,false)
insert into root.ln.wf01.wt01(timestamp,status) values(1509465840000,false)
create timeseries root.ln.wf02.wt02.hardware with datatype=TEXT,encoding=PLAIN
insert into root.ln.wf02.wt02(timestamp,hardware) values(1510029720000,"v2")
insert into root.ln.wf02.wt02(timestamp,hardware) values(1510029780000,"v1")
insert into root.ln.wf02.wt02(timestamp,hardware) values(1510030020000,"v1")
set storage group to root.sgcc
create timeseries root.sgcc.wf03.wt01.status with datatype=BOOLEAN,encoding=PLAIN
insert into root.sgcc.wf03.wt01(timestamp,status) values(1509534180000,false)
insert into root.sgcc.wf03.wt01(timestamp,status) values(1509534300000,true)
insert into root.sgcc.wf03.wt01(timestamp,status) values(1509534600000,false)
根据本文描述的数据属性层级,按照属性涵盖范围以及它们之间的从属关系,可将其表示为如下图2.1的属性
层级组织结构,其层级关系为:集团层-电场层-设备层-传感器层。其中ROOT为根节点,传感器层的每一个节
点称为叶子节点。在使用IoTDB的过程中,您可以直接将由ROOT节点到每一个叶子节点路径上的属性用 “.”
连接,将其作为一个IoTDB的时间序列的名称。图2.1中最左侧的路径可以生成一个名为 ROOT.ln.wf01.wt01.status
的时间序列。
得到时间序列的名称之后,我们需要根据数据的实际场景和规模设置存储组。由于在本文所述场景中,每次到达的数据通常以集团为单位(即数据可能为跨电场、跨设备的),为了写入数据时避免频繁切换IO降低系统速度,且满足用户以集团为单位进行物理隔离数据的要求,我们将存储组设置在集团层。
设备
设备指的是在实际场景中拥有传感器的装置。在IoTDB当中,所有的传感器都应有其对应的归属的设备。
传感器
传感器是指在实际场景中的一种检测装置,它能感受到被测量的信息,并能将感受到的信息按一定规律变换成为电信号或其他所需形式的信息输出并发送给IoTDB。在IoTDB当中,存储的所有的数据及路径,都是以传感器为单位进行组织。
存储组
用户可以将任意前缀路径设置成存储组。如有4条时间序列 root.vehicle.d1.s1
, root.vehicle.d1.s2
, root.vehicle.d2.s1
, root.vehicle.d2.s2
,路径 root.vehicle
下的两个设备d1,d2可能属于同一个业主,或者同一个厂商,因此关系紧密。这时候就可以将前缀路径 root.vehicle
指定为一个存储组,这将使得IoTDB将其下的所有设备的数据存储在同一个文件夹下。未来 root.vehicle
下增加了新的设备,也将属于该存储组。
注意:不允许将一个完整路径(如上例的
root.vehicle.d1.s1
)设置成存储组。
设置合理数量的存储组可以带来性能的提升:既不会因为产生过多的存储文件(夹)导致频繁切换IO降低系统速度(并且会占用大量内存且出现频繁的内存-文件切换),也不会因为过少的存储文件夹(降低了并发度从而)导致写入命令阻塞。
用户应根据自己的数据规模和使用场景,平衡存储文件的存储组设置,以达到更好的系统性能。(未来会有官方提供的存储组规模与性能测试报告)
注意:一个时间序列其前缀必须属于某个存储组。在创建时间序列之前,用户必须设定该序列属于哪个存储组(Storage Group)。只有设置了存储组的时间序列才可以被持久化在磁盘上。
一个前缀路径一旦被设定成存储组后就不可以再更改这个存储组的设置。
一个存储组设定后,其对应的前缀路径的所有父层级与子层级也不允许再设置存储组(如,root.ln
设置存储组后,root层级与root.ln.wf01
不允许被设置为存储组)。
路径
在IoTDB中,路径是指符合以下约束的表达式:
path: LayerName (DOT LayerName)+
LayerName: Identifier | STAR
其中STAR为“*”,DOT为“.”。
我们称一个路径中在两个“.”中间的部分叫做一个层级,则 root.a.b.c
是一个层级为4的路径。
值得说明的是,在路径中,root为一个保留字符,它只允许出现在下文提到的时间序列的开头,若其他层级出现root,则无法解析,提示报错。
时间序列
时间序列是IoTDB中的核心概念。时间序列可以被看作产生时序数据的传感器的所在完整路径,在IoTDB中所有的时间序列必须以root开始、以传感器作为结尾。一个时间序列也可称为一个全路径。
例如,vehicle种类的device1有名为sensor1的传感器,则它的时间序列可以表示为:root.vehicle.device1.sensor1
。
注意:当前IoTDB支持的时间序列必须大于等于四层(之后会更改为两层)。
前缀路径
前缀路径是指一个时间序列的前缀所在的路径,一个前缀路径包含以该路径为前缀的所有时间序列。例如当前我们有root.vehicle.device1.sensor1
, root.vehicle.device1.sensor2
, root.vehicle.device2.sensor1
三个传感器,则root.vehicle.device1
前缀路径包含root.vehicle.device1.sensor1
、root.vehicle.device1.sensor2
两个时间序列,而不包含root.vehicle.device2.sensor1
。
带*
路径
为了使得在表达多个时间序列或表达前缀路径的时候更加方便快捷,IoTDB为用户提供带*
路径。*
可以出现在路径中的任何层。按照*
出现的位置,带*
路径可以分为两种:
1、 *
出现在路径的结尾;
当*
出现在路径的结尾时,其代表的是(*
)+,即为一层或多层*
。例如root.vehicle.device1.*
代表的是root.vehicle.device1.*
, root.vehicle.device1.*.*
, root.vehicle.device1.*.*.*
等所有以root.vehicle.device1
为前缀路径的大于等于4层的路径。
2、 *
出现在路径的中间;
当*
出现在路径的中间,其代表的是*
本身,即为一层。例如root.vehicle.*.sensor1
代表的是以root.vehicle
为前缀,以sensor1
为后缀,层次等于4层的路径。
注意:
*
不能放在路径开头。 注意:*
放在末尾时与前缀路径表意相同,例如root.vehicle.*
与root.vehicle
为相同含义。
时间戳
时间戳是一个数据到来的时间点,其中包括绝对时间戳和相对时间戳。
绝对时间戳
IOTDB中绝对时间戳分为二种,一种为LONG类型,一种为DATETIME类型
(包含DATETIME-INPUT, DATETIME-DISPLAY两个小类)。
在用户在输入时间戳时,可以使用LONG类型的时间戳或DATETIME-INPUT类型的时间戳,其中DATETIME-INPUT类型的时间戳支持格式如下所示:
DATETIME-INPUT类型支持格式
yyyy-MM-dd HH:mm:ss
yyyy/MM/dd HH:mm:ss
yyyy.MM.dd HH:mm:ss
yyyy-MM-dd'T'HH:mm:ss
yyyy/MM/dd'T'HH:mm:ss
yyyy.MM.dd'T'HH:mm:ss
yyyy-MM-dd HH:mm:ssZZ
yyyy/MM/dd HH:mm:ssZZ
yyyy.MM.dd HH:mm:ssZZ
yyyy-MM-dd'T'HH:mm:ssZZ
yyyy/MM/dd'T'HH:mm:ssZZ
yyyy.MM.dd'T'HH:mm:ssZZ
yyyy/MM/dd HH:mm:ss.SSS
yyyy-MM-dd HH:mm:ss.SSS
yyyy.MM.dd HH:mm:ss.SSS
yyyy/MM/dd'T'HH:mm:ss.SSS
yyyy-MM-dd'T'HH:mm:ss.SSS
yyyy.MM.dd'T'HH:mm:ss.SSS
yyyy-MM-dd HH:mm:ss.SSSZZ
yyyy/MM/dd HH:mm:ss.SSSZZ
yyyy.MM.dd HH:mm:ss.SSSZZ
yyyy-MM-dd'T'HH:mm:ss.SSSZZ
yyyy/MM/dd'T'HH:mm:ss.SSSZZ
yyyy.MM.dd'T'HH:mm:ss.SSSZZ
ISO8601 standard time format
IoTDB在显示时间戳时可以支持LONG类型以及DATETIME-DISPLAY类型,其中DATETIME-DISPLAY类型可以支持用户自定义时间格式。自定义时间格式的语法如表所示:
DATETIME-DISPLAY自定义时间格式的语法
Symbol | Meaning | Presentation | Examples |
---|---|---|---|
G | era | era | era |
C | century of era (>=0) | number | 20 |
Y | year of era (>=0) | year | 1996 |
x | weekyear | year | 1996 |
w | week of weekyear | number | 27 |
e | day of week | number | 2 |
E | day of week | text | Tuesday; Tue |
y | year | year | 1996 |
D | day of year | number | 189 |
M | month of year | month | July; Jul; 07 |
d | day of month | number | 10 |
a | halfday of day | text | PM |
K | hour of halfday (0~11) | number | 0 |
h | clockhour of halfday (1~12) | number | 12 |
H | hour of day (0~23) | number | 0 |
k | clockhour of day (1~24) | number | 24 |
m | minute of hour | number | 30 |
s | second of minute | number | 55 |
S | fraction of second | millis | 978 |
z | time zone | text | Pacific Standard Time; PST |
Z | time zone offset/id | zone | -0800; -08:00; America/Los_Angeles |
‘ | escape for text | delimiter | |
‘’ | single quote | literal | ‘ |
相对时间戳
相对时间是指与服务器时间now()
和DATETIME
类型时间相差一定时间间隔的时间。 形式化定义为:
Duration = (Digit+ ('Y'|'MO'|'W'|'D'|'H'|'M'|'S'|'MS'|'US'|'NS'))+
RelativeTime = (now() | DATETIME) ((+|-) Duration)+
The syntax of the duration unit
Symbol | Meaning | Presentation | Examples |
---|---|---|---|
y | year | 1y=365 days | 1y |
mo | month | 1mo=30 days | 1mo |
w | week | 1w=7 days | 1w |
d | day | 1d=1 day | 1d |
h | hour | 1h=3600 seconds | 1h |
m | minute | 1m=60 seconds | 1m |
s | second | 1s=1 second | 1s |
ms | millisecond | 1ms=1000_000 nanoseconds | 1ms |
us | microsecond | 1us=1000 nanoseconds | 1us |
ns | nanosecond | 1ns=1 nanosecond | 1ns |
例子:
now() - 1d2h //比服务器时间早1天2小时的时间
now() - 1w //比服务器时间早1周的时间
注意:’+’和’—‘的左右两边必须有空格
数据类型
IoTDB支持:
- BOOLEAN(布尔值)
- INT32(整型)
- INT64(长整型)
- FLOAT(单精度浮点数)
- DOUBLE(双精度浮点数)
- TEXT(字符串)
一共六种数据类型。
其中FLOAT与DOUBLE类型的序列,如果编码方式采用RLE或TS_2DIFF可以指定MAX_POINT_NUMBER,该项为浮点数的小数点后位数。
压缩方式
当时间序列写入并按照指定的类型编码为二进制数据后,IoTDB会使用压缩技术对该数据进行压缩,进一步提升空间存储效率。虽然编码和压缩都旨在提升存储效率,但编码技术通常只适合特定的数据类型(如二阶差分编码只适合与INT32或者INT64编码,存储浮点数需要先将他们乘以10m以转换为整数),然后将它们转换为二进制流。压缩方式(SNAPPY)针对二进制流进行压缩,因此压缩方式的使用不再受数据类型的限制。
IoTDB允许在创建一个时间序列的时候指定该列的压缩方式。现阶段IoTDB现在支持的压缩方式有两种:
- UNCOMPRESSED(不压缩)
- SNAPPY压缩