IoTDB
是一款时序数据库,相关竞品有 Kairosdb
,InfluxDB
,TimescaleDB
等,主要使用场景是在物联网相关行业,如:车联网、风力发电、地铁、飞机监控等等,具体应用案例及公司详情能够查看:IoTDB在实际公司中的使用信息收集git
IoTDB
模块主要分为Client
,JDBC
,Server
,TsFile
,Grafana
,Distribution
以及各类生态的链接器。整个系列的文章会从行业背景开始讲起,了解一个行业具体的使用场景,而后介绍 TsFile
是以什么样的格式来保存数据的,再介绍 Server
里怎样完成一次查询,最后在介绍一条完 整的 SQL
是怎样从 Client
使用 JDBC
到 Server
直至返回具体结果。若是有能力的话再介绍一下集群的一些内容和工做方式。github
打一波广告本人专一车联网领域多年,现任四维智联架构师。目前正在参与 IoTDB 社区,有志同道合的同伴欢迎加微信:liutaohua001数据库
欢迎你们访问 IoTDB 仓库,求一波 Star 。apache
这一章主要想聊一聊:微信
IoTDB
的发展过程IoTDB
和竞品测试对比我我的理解时序数据是基于时间维度的同一个物体或概念的值构成的一个序列数据。在传统关系型数据库中,例如 MySQL
,咱们一般会放置一个自增的 Id
列做为主键标识,以下:架构
Id | 人名 | 体温 | 测量时间 |
---|---|---|---|
1 | 张三 | 36.5 | 2020-02-06 9:00:00 |
2 | 李四 | 36.9 | 2020-02-06 9:00:00 |
3 | 王五 | 36.7 | 2020-02-06 9:00:00 |
4 | 张三 | 36.3 | 2020-02-06 9:30:00 |
5 | 张三 | 36.9 | 2020-02-06 11:00:00 |
上面的表结构就是一个时序数据,将表结构作个变形更容易理解:工具
时间戳 | 人名 | 体温 |
---|---|---|
1580950800 | 张三 | 36.5 |
1580950800 | 李四 | 36.9 |
1580950800 | 王五 | 36.7 |
1580952600 | 张三 | 36.3 |
1580958000 | 张三 | 36.9 |
若是把时间做为一个惟一键对齐展现,可以更像时序数据一些,这也是 IoTDB
中查询结果的展现方式:性能
时间戳 | 张三 | 李四 | 王五 |
---|---|---|---|
1580950800 | 36.5 | 36.9 | 36.7 |
1580952600 | 36.3 | NULL | NULL |
1580958000 | 36.9 | NULL | NULL |
这里可能会存在疑问就是假如人数是逐渐增长的,那么是动态建立列呢?仍是提早建立足够多的列?这个问题等后面文章有机会继续介绍测试
物联网的特色是都会存在一个或多个设备,他们以各类各样的形式组织到一块儿,用来观测或记录同一时间里相同环境所产生的数据。下面的介绍中,使用由简单到复杂的数据逐步介绍在物联网行业中,通用的一些问题和方向。大数据
假如我是一个公司,对外播报北京、天津、上海三地的温度数据,从而实现盈利。
时间戳 | 北京 | 天津 | 上海 |
---|---|---|---|
1580950800 | 20.5 | 22.9 | 21.7 |
1580952600 | 20.5 | NULL | 22.9 |
1580958000 | 20.5 | 21.7 | 22.9 |
数据保证的质量是多方面的,一步一步介绍。
首先能够看到上面数据是存在 NULL
值的,这个 NULL
值有多是由于当时设备所在的区域停电了,因此并无办法上报当时的状况,这样客户若是想获取1580952600
这个时间戳对应的天津的数据的时候,确定是拿不到了,因此传统思惟上,咱们应该增长一个容灾设备,保证一个设备在坏掉、停电、人为损坏等等的状况的时候,依然可以有数据上报回来。
基于这样的思想,以上的表结构就会变成:
时间戳 | 北京 1 | 北京 2 | 天津1 | 天津2 | 上海1 | 上海2 |
---|---|---|---|---|---|---|
1580950800 | 20.5 | 20.9 | 21.7 | 20.9 | 20.7 | 21.7 |
1580952600 | 21.5 | 21.0 | NULL | 21.7 | 21.7 | 21.7 |
1580958000 | 22.5 | 22.7 | 22.9 | 22.7 | NULL | NULL |
这时候依然存在问题, 1580958000
这一刻两个设备都没有数据,有多是放置设备的区域同时出现了断网或者断电,这种状况下,咱们能够采用提升采集数据的频率或者补传数据来解决(补传暂不讨论)。
咱们将天天数据分为3组,每组采样3次,间隔为1个小时,假如时间分布为:上午(七、八、9)、中午(十二、1三、14)、下午(1八、1九、20)。当增长了采样频率以后,即使某一刻出现了 NULL 数据,咱们也能够采用临近时间作为补充。为了方便对应,下表数据中增长时间点列辅助查看。
时间点 | 时间戳 | 北京 1 | 北京 2 | 天津1 | 天津2 | 上海1 | 上海2 |
---|---|---|---|---|---|---|---|
7点 | 1580943600 | 20.5 | 20.9 | 21.7 | 20.9 | 20.7 | 21.7 |
8点 | 1580947200 | 21.5 | 21.0 | NULL | 21.7 | 21.7 | 21.7 |
9点 | 1580950800 | 22.5 | 22.7 | 22.9 | 22.7 | NULL | NULL |
12点 | 1580961600 | 20.5 | 20.9 | 21.7 | 20.9 | 20.7 | 21.7 |
13点 | 1580965200 | 21.5 | 21.0 | NULL | 21.7 | 21.7 | 21.7 |
14点 | 1580968800 | 22.5 | 22.7 | 22.9 | 22.7 | NULL | NULL |
18点 | 1580983200 | 20.5 | 20.9 | 21.7 | 20.9 | 20.7 | 21.7 |
19点 | 1580986800 | 21.5 | 21.0 | NULL | 21.7 | 21.7 | 21.7 |
20点 | 1580990400 | 22.5 | 22.7 | 22.9 | 22.7 | NULL | NULL |
能够看到通过各类各样的需求以后,上传的数据是成倍增加的,不难想象若是这个温度数据但愿精准的获取到每一个县城的温度,那么中国有 2854 个县城 * 2 个温度设备 * 9 条数据 = 1 天产生的数据总量 = 51372 条,那么一个月就是 1541160 条。
假如上面的数据咱们继续提升频率到每1分钟每一个设备上报一次,那么数据量就会成为 2854 * 2 * 60 * 24 = 246585600 条/天。
在这样的数据量下,实时插入实时作一些聚合计算,应该传统数据库就有些处理不过来了。
某公司在实际业务中,20 万设备保存了 3 年的数据,TB级别的数据使得 Oracle 被拖的根本吃不消。关键的问题点还不只仅是存量数据大,新增数据依然以很是快的速度在增加。后来公司联系到了 IoTDB
的第一批开发者,可是当时的方案仍是基于 Cassandra 来作设计,当时规划了 5 台机器的集群,性能刚知足,但随着时间推移设备总量在增长,业务系统的查询请求量在增长。Cassandra 在通过大量的努力以后,最后发现若是再改可能就须要大面积的重构 Cassandra 数据的代码了,最终决定从新设计一个存储方式,来解决物联网场景下的时序数据高效写入、低延迟读取、高压缩比持久化。
PS: 以上都是黄向东 (IoTDB PPMC) ,在 meetup 中讲到的,我只是在脑中存留了一部分,具体的细节你们能够到 IoTDB 社区交流。
测试工具使用的是由清华大学大数据实验室开发的iotdb-benchmark
数据集2 | 客户端 | 存储组 | 设备 | 变量 | batchsize | LOOP | 数据量 | 写入速度(point/s) | 硬盘数据大小 |
---|---|---|---|---|---|---|---|---|---|
IoTDB | 10 | 10 | 10 | 10 | 1000 | 1000000 | 1E+11 | 24750321.93 | 38306092 |
InfluxDB | 10 | 10 | 10 | 10 | 1000 | 1000000 | 1E+11 | 304682932 | |
TimescaleDB | 10 | 10 | 10 | 10 | 1000 | 1000000 | 1E+11 | 737689.22 | 1610219064 |
数据集1 | 客户端 | 存储组 | 设备 | 变量 | batchsize | LOOP | 数据量 | 写入速度(point/s) | 硬盘数据大小 |
---|---|---|---|---|---|---|---|---|---|
IoTDB | 10 | 10 | 10 | 10 | 1000 | 100000 | 10000000000 | 20706345.15 | 3599732 |
InfluxDB | 10 | 10 | 10 | 10 | 1000 | 100000 | 10000000000 | 1729907.81 | 30546560 |
TimescaleDB | 10 | 10 | 10 | 10 | 1000 | 100000 | 10000000000 | 715857 | 161026468 |
KairosDB | 10 | 10 | 10 | 10 | 10000 | 10000 | 10000000000 | 24924.97 | 76263380 |
上面一组数据能够看出写入性能高于同款数据库10倍有余,单机写入速度高达到每秒2千万。且硬盘占用是最小的,这在数据比较大的线上业务中,可能每月会差出来 1 到 2 块硬盘。
原始数据查询
客户端 | 存储组 | 设备 | 序列-数据量 | 变量 | 查询点数 | LOOP | 速度(point/s) | AVG | MIN | |
---|---|---|---|---|---|---|---|---|---|---|
IoTDB | 10 | 10 | 10 | 1.00E+09 | 1 | 1000000 | 100 | 12942984.85 | 740.27 | 457.04 |
InfluxDB | 10 | 10 | 10 | 1.00E+09 | 1 | 1000000 | 100 | 1779606.4 | 5591 | 4666.39 |
TimescaleDB | 10 | 10 | 10 | 1.00E+09 | 1 | 1000000 | 100 | 3781467.52 | 2345.69 | 1193.78 |
聚合数据查询
客户端 | 存储组 | 设备 | 序列-数据量 | 变量 | LOOP | 范围 | 速度(point/s) | AVG | MIN | |
---|---|---|---|---|---|---|---|---|---|---|
IoTDB-1 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.0001 | 49.75 | 27.87 | 18.03 |
IoTDB-2 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.001 | 49.75 | 49.14 | 19.87 |
IoTDB-3 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.01 | 49.76 | 48.69 | 22.32 |
IoTDB-4 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.1 | 48.68 | 99.14 | 25.56 |
IoTDB-5 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 1 | 14 | 595.61 | 45.54 |
InfluxDB-1 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.0001 | 234.32 | 40.28 | 21.63 |
InfluxDB-2 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.001 | 28.88 | 341.9 | 238.1 |
InfluxDB-3 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.01 | 3.07 | 3226.87 | 2664.86 |
TimescaleDB-1 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.0001 | 42.39 | 220.57 | 120.5 |
TimescaleDB-2 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.001 | 5.8 | 1502.9 | 754.15 |
TimescaleDB-3 | 10 | 10 | 10 | 1.00E+09 | 1 | 100 | 0.01 | 1.02 | 9711.55 | 7148.69 |
总体来看 IoTDB
不管在写入、原始数据查询仍是聚合查询,都几乎是10倍的性能于竞品数据库,并且硬盘占用又小于同款数据库10倍,那么 IoTDB
是怎样完成如此高的压缩比、如此恐怖的写入速度、如此高效的查询呢?欢迎继续关注。。。