近日,咱们曾发布测试报告 DolphinDB与InfluxDB对比测试报告,此报告测试于2019年。当时的结果显示,DolphinDB的查询性能领先InfluxDB一到三个数据量级,数据导入性能领先一个数量级,数据导出性能相差不大。时隔一年,DolphinDB与InfluxDB都作了很多功能和性能上的优化,二者的性能究竟有何变化?咱们从新对DolphinDB Database 和InfluxDB进行对比测试,测试涵盖数据导入导出、数据查询和磁盘空间占用三个方面。测试的数据集也涵盖了日益流行的物联网数据集,以及规模更大的金融大数据集。git
在本次的全部测试项目中,DolphinDB 表现更出色,主要测试结论以下:github
查询功能方面,InfluxDB 不支持对比查询,不支持表链接,不支持对除 time 之外的 tag, field 进行排序,且函数的参数只能是某一个 field ,而不能是 field 的表达式,功能上有极大的限制,有多个测试样例没法在sql
InfluxDB 中实现;而 DolphinDB 对数据的处理则更加的灵活、方便。
数据库
DolphinDB编程
DolphinDB 是以 C++ 编写的一款分析型的高性能分布式时序数据库,使用高吞吐低延迟的列式内存引擎,集成了功能强大的编程语言和高容量高速度的流数据分析系统,可在数据库中进行复杂的编程和运算,显著减小数据迁移所耗费的时间。windows
DolphinDB 经过内存引擎、数据本地化、细粒度数据分区和并行计算实现高速的分布式计算,内置流水线、 Map Reduce 和迭代计算等多种计算框架,使用内嵌的分布式文件系统自动管理分区数据及其副本,为分布式计算提供负载均衡和容错能力。缓存
DolphinDB 支持类标准 SQL 的语法,提供相似于 Python 的脚本语言对数据进行操做,也提供其它经常使用编程语言的 API,在金融领域中的历史数据分析建模与实时流数据处理,以及物联网领域中的海量传感器数据处理与实时分析等场景中表现出色。性能优化
InfluxDBapp
InfluxDB 是目前最为流行的高性能开源时间序列数据库,由 Go 语言写成。它的核心是一款定制的存储引擎 TSM Tree,对时间序列数据作了优化,优先考虑插入和查询数据的性能。负载均衡
InfluxDB 使用类 SQL 的查询语言 InfluxQL,并提供开箱即用的时间序列数学和统计函数;同时对外提供基于 HTTP 的接口来支持数据的插入与查询
InfluxDB 容许用户定义数据保存策略 (Retention Policies) 来实现对存储超过指定时间的数据进行删除或者降采样,被普遍应用于存储系统的监控数据,IoT 行业的实时数据等场景。
因为 InfluxDB 集群版本闭源,在测试中 DolphinDB 与 InfluxDB 均使用单机模式。
主机:DELL OptiPlex 7060
CPU :Intel Core i7-8700(6 核 12 线程 3.20 GHz)
内存:32 GB (8GB × 4, 2666 MHz)
硬盘:2T HDD (222 MB/s 读取;210 MB/s 写入)
OS:Ubuntu 16.04 LTS
测试使用的 DolphinDB 版本为 Linux v0.89 (2019.01.31),最大内存设置为 28GB
。
测试使用的 InfluxDB 版本为 1.7.5,根据 InfluxDB 官方配置文件中的说明,结合测试机器的实际硬件对配置作了优化,主要将 wal-fsync-delay
调节为适合机械硬盘的 100ms
,将 cache-max-memory-size
设置为 28GB
,以及将 series-id-set-cache-size
设置为 400
。
具体修改的配置详见附录中 influxdb.conf
文件。
本报告测试了小数据量级(4.2GB)和大数据量级(270GB)下DolphinDB和InfluxDB的表现状况,如下是两个数据的表结构和分区方法:
4.2GB设备传感器记录小数据集(csv格式,3千万条)
咱们使用物联网设备的传感器信息做为小数据集来测试,数据集包含3000个设备在2016年11月15日到2016年11月19日10000个时间间隔上的传感器时间,设备ID,电池,内存,CPU等时序统计信息。数据集共30,000,000条数据,包含包含一张设备信息表device_info和一张设备传感器信息记录表readings。
数据来源:https://docs.timescale.com/v1.1/tutorials/other-sample-datasets
下载地址:https://timescaledata.blob.core.windows.net/datasets/devices_big.tar.gz
如下是readings表在DolphinDB和InfluxDB中的结构:
2018年8月,咱们曾发布测试报告 DolphinDB与InfluxDB对比测试报告。当时的结果显示,DolphinDB的查询性能领先InfluxDB一到三个数据量级,数据导入性能领先一个数量级,数据导出性能相差不大。时隔半年,DolphinDB与InfluxDB都作了很多功能和性能上的优化,二者的性能究竟有何变化?咱们从新对DolphinDB和InfluxDB进行对比测试,测试涵盖数据导入导出、数据查询和磁盘空间占用三个方面。测试的数据集也涵盖了日益流行的物联网数据集,以及规模更大的金融大数据集。
在本次的全部测试项目中,DolphinDB 表现更出色,主要测试结论以下:
DolphinDB
DolphinDB 是以 C++ 编写的一款分析型的高性能分布式时序数据库,使用高吞吐低延迟的列式内存引擎,集成了功能强大的编程语言和高容量高速度的流数据分析系统,可在数据库中进行复杂的编程和运算,显著减小数据迁移所耗费的时间。
DolphinDB 经过内存引擎、数据本地化、细粒度数据分区和并行计算实现高速的分布式计算,内置流水线、 Map Reduce 和迭代计算等多种计算框架,使用内嵌的分布式文件系统自动管理分区数据及其副本,为分布式计算提供负载均衡和容错能力。
DolphinDB 支持类标准 SQL 的语法,提供相似于 Python 的脚本语言对数据进行操做,也提供其它经常使用编程语言的 API,在金融领域中的历史数据分析建模与实时流数据处理,以及物联网领域中的海量传感器数据处理与实时分析等场景中表现出色。
InfluxDB
InfluxDB 是目前最为流行的高性能开源时间序列数据库,由 Go 语言写成。它的核心是一款定制的存储引擎 TSM Tree,对时间序列数据作了优化,优先考虑插入和查询数据的性能。
InfluxDB 使用类 SQL 的查询语言 InfluxQL,并提供开箱即用的时间序列数学和统计函数;同时对外提供基于 HTTP 的接口来支持数据的插入与查询
InfluxDB 容许用户定义数据保存策略 (Retention Policies) 来实现对存储超过指定时间的数据进行删除或者降采样,被普遍应用于存储系统的监控数据,IoT 行业的实时数据等场景。
因为 InfluxDB 集群版本闭源,在测试中 DolphinDB 与 InfluxDB 均使用单机模式。
主机:DELL OptiPlex 7060
CPU :Intel Core i7-8700(6 核 12 线程 3.20 GHz)
内存:32 GB (8GB × 4, 2666 MHz)
硬盘:2T HDD (222 MB/s 读取;210 MB/s 写入)
OS:Ubuntu 16.04 LTS
测试使用的 DolphinDB 版本为 Linux v0.89 (2019.01.31),最大内存设置为 28GB
。
测试使用的 InfluxDB 版本为 1.7.5,根据 InfluxDB 官方配置文件中的说明,结合测试机器的实际硬件对配置作了优化,主要将 wal-fsync-delay
调节为适合机械硬盘的 100ms
,将 cache-max-memory-size
设置为 28GB
,以及将 series-id-set-cache-size
设置为 400
。
具体修改的配置详见附录中 influxdb.conf
文件。
本报告测试了小数据量级(4.2GB)和大数据量级(270GB)下DolphinDB和InfluxDB的表现状况,如下是两个数据的表结构和分区方法:
4.2GB设备传感器记录小数据集(csv格式,3千万条)
咱们使用物联网设备的传感器信息做为小数据集来测试,数据集包含3000个设备在2016年11月15日到2016年11月19日10000个时间间隔上的传感器时间,设备ID,电池,内存,CPU等时序统计信息。数据集共30,000,000条数据,包含包含一张设备信息表device_info和一张设备传感器信息记录表readings。
数据来源:https://docs.timescale.com/v1.1/tutorials/other-sample-datasets
下载地址:https://timescaledata.blob.core.windows.net/datasets/devices_big.tar.gz
如下是readings表在DolphinDB和InfluxDB中的结构:
咱们在 DolphinDB database 中的分区方案是将 time
做为分区的第一个维度,按天分为 4 个区,分区边界为 [2016.11.15 00:00:00, 2016.11.16 00:00:00, 2016.11.17 00:00:00, 2016.11.18 00:00:00, 2016.11.19 00:00:00]
;再将 device_id
做为分区的第二个维度,天天一共分 10 个区,最后每一个分区所包含的原始数据大小约为 100 MB
。
InfluxDB 中使用 Shard Group 来存储不一样时间段的数据,不一样 Shard Group 对应的时间段不会重合。一个 Shard Group 中包含了大量的 Shard, Shard 才是 InfluxDB 中真正存储数据以及提供读写服务的结构。InfluxDB 采用了 Hash 分区的方法将落到同一个 Shard Group 中的数据再次进行了一次分区,即根据 hash(Series) 将时序数据映射到不一样的 Shard,所以咱们使用如下语句手动指定每一个 Shard Group 的 Duration,在时间维度上按天分区。
create retention policy one_day on test duration inf replication 1 shard duration 1d default
270GB股票交易大数据集(csv格式,23个csv,65亿条)
咱们将纽约证券交易所(NYSE)提供的 2007.08.01 - 2007.08.31 一个月的股市 Level 1 报价数据做为大数据集进行测试,数据集包含 8000 多支股票在一个月内的交易时间
,股票代码
,买入价
,卖出价
,买入量
,卖出量
等报价信息。
数据集中,共有 65 亿(65,6169,3704)条报价记录,一个 CSV 中保存一个交易日的记录,该月共 23 个交易日,未压缩的 CSV 文件共计 270 GB。
数据来源:NYSE Exchange Proprietary Market Data
如下是TAQ表在DolphinDB和InfluxDB中的结构:
在 DolphinDB database 中咱们按date(日期)
,symbol(股票代码)
进行分区,天天再根据 symbol 分为 100 个分区,每一个分区大概 120 MB 左右。
在InfluxDB中使用与小数据集相同的策略。
DolphinDB使用如下脚本导入:
timer { for (fp in fps) { loadTextEx(db, `taq, `date`symbol, fp, ,schema) print now() + ": 已导入 " + fp } }
4.2 GB 设备传感器记录小数据集共3 千万条数据导入用时 20 秒
, 平均速率 150 万条/秒
。
270 GB 股票交易大数据集共 65 亿条数据(TAQ20070801 - TAQ20070831
23 个文件),导入用时 38 分钟
。
InfluxDB 自己不支持直接导入 CSV,只能经过 HTTP API 或者influx -import
的方式导入,出于导入性能考虑,咱们选择将 CSV 中的每一行先转换为 Line Protocol 格式,如:
readings,device_id=demo000000,battery_status=discharging,bssid=A0:B1:C5:D2:E0:F3,ssid=stealth-net battery_level=96,battery_temperature=91.7,cpu_avg_1min=5.26,cpu_avg_5min=6.172,cpu_avg_15min=6.51066666666667,mem_free=650609585,mem_used=349390415,rssi=-42 1479211200
并添加以下文件头:
# DDL CREATE DATABASE test CREATE RETENTION POLICY one_day ON test DURATION INF REPLICATION 1 SHARD DURATION 1d DEFAULT # DML # CONTEXT-DATABASE:test # CONTEXT-RETENTION-POLICY:one_day
保存到磁盘中,再经过如下命令导入:
influx -import -path=/data/devices/readings.txt -precision=s -database=test
通过转换后,4.2 GB 设备传感器记录小数据集共3 千万
条数据导入用时25 分钟 10 秒
, 平均速率2 万条/秒
。
将 TAQ 数据插入到 InfluxDB 的过程当中,若是屡次插入时间相同 (1185923302),tag 相同的记录 (这里是 symbol, mode, ex),好比下面两条,即便 value 不一样 (bid, ofr, bidsiz, ofrsiz),后面的那一条记录也会覆盖前面的记录,最终数据库中只保留了最后一条记录。
taq,symbol=A,mode=12,ex=T bid=37,ofr=54.84,bidsiz=1,ofrsiz=1 1185923302 taq,symbol=A,mode=12,ex=T bid=37,ofr=38.12,bidsiz=1,ofrsiz=1 1185923302
要解决这个问题文档(InfluxDB frequently asked questions | InfluxData Documentation)里给出了两种方法,一种是新增一个 tag 来对相同时间的数据设置不一样的 tag value 手动区分,另外一种是强行微调时间戳使其不一样。
设置不一样的 tag value 手动区分这种方法只适用于数据彻底按照时间顺序插入的状况。在使用其余的编程语言插入数据的过程当中判断该条记录的时间戳是否与上一条记录彻底相同,并在插入数据库时手动指定不一样的 tag value 做区分,效率低下且操做繁琐;若数据并不是彻底按照时间顺序插入,则没法判断当前的时间点是否已经有数据记录的存在,是否会覆盖先前的数据。
咱们在本次测试中使用强行微调时间戳的方法,因为原有 TAQ 交易记录的时间精度为秒,所以咱们能够在将 CSV 的数据转换至 Line Protocol 格式的过程当中,在原来精确到秒的时间戳的基础上,随机加上一个毫秒值,产生一个新的精度为毫秒的伪时间戳,以防止数据冲突。
通过转换后,270 GB 股票交易大数据集所包含的65 亿
条数据导入用时65 小时
,平均导入速率2.7 万条/秒
。
导入性能对好比下表所示:
结果显示,DolphinDB 的导入速率远大于 InfluxDB 的导入速率。在导入过程当中还能够观察到,随着时间的推移,InfluxDB 的导入速率不断降低,而 DolphinDB 保持稳定。并且 InfluxDB 在导入数据时须要先编写代码将 CSV 格式文件转换为 InfluxDB 的 Line Protocol 格式,复杂繁琐,还会产生多余的中间文件占用大量空间。
在 DolphinDB 中使用saveText((select * from readings), '/data/devices/readings_dump.csv')
进行数据导出,用时仅需 28 秒。
在 InfluxDB 中若使用influx -database 'test' -format csv -execute "select * from readings > /data/devices/export_15.csv
进行数据导出内存占用会超过 30 GB,最终引起fatal error: runtime: out of memory
,最后采用分时间段导出 CSV 的方法。代码以下所示:
for i in 1{5..8}; do time influx -database 'test' -format csv -execute "select * from readings where '2016-11-$i 00:00:00' <= time and time < '2016-11-$((i+1)) 00:00:00'" > /data/devices/export_$i.csv done
总耗时5 min 31 s。
除性能差距悬殊以外,InfluxDB 的 CSV 数据导出操做复杂,容易发生内存溢出问题,并且导出的 CSV 文件首行无字段名称,用户体验远不如 DolphinDB。
导出性能对好比下表所示:
导入数据后,DolphinDB和InfluxDB占用空间以下表所示:
小数据集中 DolphinDB 的空间利用率与 InfluxDB 相近,两款数据库都对数据进行了压缩存储,压缩率大体处于同一个数量级,在 20% - 30% 之间;大数据集中 InfluxDB 对数据的压缩效果很差,占用空间为 DolphinDB 的两倍。
咱们一共对比了如下八种类别的查询:
查询测试的时间包含磁盘 I/O 的时间,为保证测试公平,每次启动程序测试前均经过 Linux 系统命令sync; echo 1,2,3 | tee /proc/sys/vm/drop_caches
分别清除系统的页面缓存、目录项缓存和硬盘缓存,启动程序后依次执行全部查询语句执行一次。
4.2GB设备传感器记录小数据集查询测试结果以下表所示:
查询脚本见附录。
结果显示,DolphinDB的查询性能远超于InfluxDB。在功能上,InfluxDB不如DolphinDB强大,好比:
select * from taq order by <some-field>
,详见[feature request] ORDER BY tag values · Issue #3954 · influxdata/influxdb。field1 + field2
等)所以只能用 subquery 先计算出表达式的值再套用函数,很是繁琐,并且须要在子查询和父查询的 where 子句中重复指定时间范围,不然会从最旧的数据记录的时间开始一直扫描到当前时间。 InfluxDB 和 DolphinDB 第14个查询语句的对好比下://14. 经典查询:计算某时间段内高负载高电量设备的内存大小 //DolphinDB select max(date(time)) as date, max(mem_free + mem_used) as mem_all from readings where time <= 2016.11.18 21:00:00, battery_level >= 90, cpu_avg_1min > 90 group by hour(time), device_id //InfluxDB select max(mem_total) from ( select mem_free + mem_used as mem_total from readings where time <= '2016-11-18 21:00:00' and battery_level >= 90 and cpu_avg_1min > 90 ) where time <= '2016-11-18 21:00:00' group by time(1h), device_id
270GB股票交易大数据查询测试结果以下表所示:
查询脚本见附录。
结果显示,某些查询,二者的性能差异不大,但某些查询,DolphinDB比InfluxDB快将近100到200倍。
在测试中,咱们发现:
//2. 范围查询:查询某时间段内的某些股票的全部记录 select symbol, time, bid, ofr from taq where (symbol = 'IBM' or symbol = 'MSFT' or symbol = 'GOOG' or symbol = 'YHOO') and ('2007-08-03 01:30:00' <= time and time < '2007-08-03 01:30:59') //该语句返回的结果不为空 select symbol, time, bid, ofr from taq where (symbol = 'IBM' or symbol = 'MSFT' or symbol = 'GOOG' or symbol = 'YHOO') and (('2007-08-03 01:30:00' <= time and time < '2007-08-03 01:30:59') or ('2007-08-04 01:30:00' <= time and time < '2007-08-04 01:30:59')) //扩展了时间范围后,该语句返回的结果反而为空
//8. 经典查询:计算某天每一个股票每分钟最大卖出与最小买入价之差 select symbol, max(ofr) - min(bid) as gap from taq where '2007-08-03' <= time and time < '2007-08-04' and bid > 0 and ofr > bid group by symbol, time(1m)
InfluxDB会抛出异常,ERR: mixing multiple selector functions with tags or fields is not supported
,即不能在select语句中同时使用max和min函数,而DolphinDB能够正常执行。
2007-07-31T23:02:00Z 22.17 54.84 2007-07-31T23:03:00Z 2007-07-31T23:04:00Z 2007-07-31T23:05:00Z 2007-07-31T23:06:00Z 2007-07-31T23:07:00Z 2007-07-31T23:08:00Z 37 38.12 2007-07-31T23:09:00Z 2007-07-31T23:10:00Z 37.03 38.12
DolphinDB 除了在基准测试中体现出优越的性能以外,还具备以下优点:
数据预览(取前20行)
DolphinDB
InfluxDB