InfluxDB是一款开源的时序数据库,由Go语言实现。它的核心是一款定制的存储引擎TSM Tree,对时间序列数据做了优化,优先考虑插入和查询数据的性能。InfluxDB使用类SQL的查询语言InfluxQL,并提供开箱即用的时间序列数学和统计函数。适用于监控、实时分析、物联网、传感器数据等应用场景。是目前最为流行的时间序列数据库。

DolphinDB Database 是一款分析型的分布式时序数据库,内置处理流式数据处理引擎,具有内置的并行和分布式计算的功能,并提供分布式文件系统,支持集群扩展。DolphinDB以C++编写,响应速度极快。提供类似于Python的脚本语言对数据进行操作,支持类标准SQL的语法。提供其它常用编程语言的API,方便与已有应用程序集成。在金融领域中的历史数据分析建模与实时流数据处理,以及物联网领域中的海量传感器数据处理与实时分析等场景中表现出色。

本文将会对DolphinDB和InfluxDB进行性能测试对比。

在本次测试中,硬件配置如下:

设备:DellXPS 8920(07DC)

CPU:Inter® Core™ i7-7700 CPU @ 3.60GHz,4核心8线程

内存:16GB

硬盘:512GB SSD

操作系统:Ubuntu 16.04 x64

由于InfluxDB集群版本闭源,所以本次测试使用的DolphinDB和InfluxDB均为单机版本,并且所有配置项都是默认配置。

1. 数据生成

在本次测试中,我们使用NYSE网站上2016年10月24日纽约交易所的股票交易数据生成了Quotes_Big表。在其中取出一部分数据构成Quotes_Small表。表结构如表1所示。Quotes_Big表中的数据量为78,721,394条,Quotes_Small表中数据量为18,314,172条。数据下载链接及预处理脚本详见附录1。

由于DolphinDB和InfluxDB在存储方式上的差异,我们采用如下设计:我们将Time列指定为InfluxDB中的timestamp;将Exchange和Symbol列指定为InfluxDB中的Tag列(类似于带索引的列);将Bid_Price、Bid_Size、Offer_Price、Offer_Size指定为InfluxDB中的field列(类似于无索引的列)。在DolphinD系统中根据Symbol列在磁盘上进行RANGE分区,分为8个区。

表1.数据类型映射

2. 数据库查询性能测试

我们对11种常用的SQL查询进行了对比测试。Quotes_Small表的测试结果如下表2所示,Quotes_Big表的测试结果如下表3所示。其中,对于DolphinDB的测试,我们使用的是DolphinDB官方的GUI;对于InfluxDB,我们使用的是官方的PythonAPI。执行时间以毫秒为单位,只包含查询本身执行的时间,而不包含结果显示的时间。为了减少特殊值的影响,每个查询都执行10次,表中数据是10次查询的总时间。本次测试的脚本详见附录2。

在几乎所有测试中,DolphinDB的性能都领先InfluxDB多倍,某些情况下的差距甚至超过2个数量级(100倍)。InfluxDB唯一领先DolphinDB的测试是在Quotes_Small表的第4个测试项目,这是由于在数据量较小时DolphinDB并行搜索分区的优势不明显。然而,在数据量较大的情况下,DolphinDB在所有测试中上的性能都优于InfluxDB。DolphinDB可以并行搜索分区的设计使它在过滤性查询方面的性能全面超过了InfluxDB。

表2. Quotes_Small表查询性能测试结果(数据量:18,314,172)

表3. Quotes_Big表查询性能测试结果(数据量:78,721,394)

3. 内置函数计算性能测试

我们测试了8个DolphinDB和InfluxDB都提供的常用内置函数。在所有测试中,DolphinDB的性能都优于InfluxDB 1-2个数量级(10-100倍)。由于DolphinDB对带有滑动窗口的函数极好的优化,在“滑动平均值”(moving_average)的测试中,DolphinDB的性能领先InfluxDB 3个数量级以上(>1000倍)。

InfluxDB在Quotes_Big表的标准差与滑动平均值计算中在长时间的卡顿后引发内存不足的问题(out of memory),说明InfluxDB对大规模数据的复杂分析场景支持不足。而DolphinDB在此方面性能优异。

Quotes_Small表的测试结果如下表4所示,Quotes_Big表的测试结果如下表5所示。表格中数据的单位为毫秒。为减少特殊值的影响,每个计算都进行了10次。测试脚本详见附录3。

表4. Quotes_Small表计算性能测试结果(数据量:18,314,172)

表5. Quotes_Big表计算性能测试结果

4. I/O性能测试

我们分别使用了DolphinDB和InfluxDB的JavaAPI,比较了在相同的环境下写入相同规模的数据所需要的时间。由于InfluxDB的默认batch-size为5000,因此在两个数据库的写入程序中,单次插入的数据量都为5000条。我们还比较了从数据库中导出同样规模的csv文件所需要的时间。比较的结果是,无论是写入性能还是导出性能,DolphinDB都优于InfluxDB。对于相同规模的18,314,172条数据,DolphinDB的导出速度为InfluxDB的2倍;写入速度约为12倍。

测试结果如下表6所示。表格中的数据单位为毫秒。测试代码详见附录4。

表6. I/O性能测试结果

5. 磁盘占用空间测试

我们比较了Quotes_Small表和Quotes_Big表由DolphinDB和InfluxDB存储后在磁盘上的占用空间。结果显示,两款数据库都对数据进行了压缩存储,压缩率大致处于同一个数量级,都在20%-30%之间,但DolphinDB的压缩效果更佳。

测试结果如下表7所示,表中的数据单位为MB。

表7. 磁盘占用空间测试结果

6.其他方面对比

DolphinDB除了在基准测试中体现出优越的性能之外,还具有如下优势:

(1)InfluxDB通过InfluxQL来操作数据库,这是一种类SQL语言;而DolphinDB内置了完整的脚本语言,不仅支持SQL语言,而且支持命令式、向量化、函数化、元编程、RPC等多种编程范式,可以轻松实现更多的功能。

(2)InfluxDB对于特定文件格式数据例如csv文件的批量导入没有很好的官方支持。用户只能通过开源第三方工具或自己实现文件的读取,规整为InfluxDB指定的输入格式,再通过API进行批量导入。单次只能导入5000行,不仅操作复杂,效率也极其低下。与之对比,DolphinDB的脚本语言中提供了loadText、loadTextEx函数,用户可以在脚本中直接导入txt或csv文件,而且效率更高,对用户更友好。

(3)DolphinDB提供400余种内置函数,可满足金融领域的历史数据建模与实时流数据处理,及物联网领域中的实时监控与数据实时分析处理等不同的场景需求。提供时序数据处理需要的领先、滞后、累积窗口、滑动窗口等多种指标的函数,且在性能上进行了优化,性能极优。 因而与InfluxDB相比,DolphinDB拥有更多的适用场景。

(4)InfluxDB不支持表连接,而DolphinDB不仅支持表连接,还对asof join及window join等非同时连接方式做了优化。

(5)InfluxDB中,对时间序列的分组(GroupBy)最大单位是星期(week);而DolphinDB支持对所有内置时间类型的分组,最大单位为月(month)。因此在时间序列这一特性上,DolphinDB也有更好的支持。

(6)DolphinDB采用分布式表引擎时支持事务,而且在一个分区的多个副本写入时,保证强一致性。

附录

附录1. 数据下载即预处理脚本

数据下载链接:nyxdata

在DolphinDB中进行数据预处理,预处理脚本如下:DATA_DIR = "…"

PTNDB_DIR = DATA_DIR + "/NYSETAQSeq"

db = database(PTNDB_DIR, SEQ, 16)

def convertTime(x) {

return string(nanotimestamp(2016.10.24).temporalAdd(x/1000, "us")).substr(0, 26)

}

// 产生 Quotes_Big.csv

Quotes = loadTextEx(db, `Quotes, , DATA_DIR+"/EQY_US_ALL_NBBO_20161024", '|')

Quotes_Big = select convertTime(time) as Time, Exchange, Symbol, Bid_Price, Bid_Size, Offer_Price, Offer_Size from Quotes

saveText(Quotes_Big, DATA_DIR + "/Quotes_Big.csv")

//产生Quotes_Small.csv

symbols = exec distinct Symbol from Quotes

symbols = symbols[0..(symbols.size() - 1) % 4 == 3]

Quotes_Small = select * from Quotes_Big where Symbol in symbols

saveText(Quotes_Small, DATA_DIR + "/Quotes_Small.csv")

// 建立数据库和数据表

if (existsDatabase(PTNDB_DIR)) {

dropDatabase(PTNDB_DIR)

}

sym = `A`D`G`J`M`P`S`V`Z

db = database(PTNDB_DIR, RANGE_PTN, symbol(sym))

// Quotes_Big表

Quotes = loadTextEx(db, `Quotes, `Symbol, DATA_DIR + “/Quotes_Big.csv”)

// Quotes_Small表

Quotes = loadTextEx(db, `Quotes, `Symbol, DATA_DIR + “/Quotes_Small.csv”)

12345678910111213141516171819202122232425262728293031

复制代码

附录2. 数据库查询性能脚本

表8. InfluxDB查询性能测试用例

表9. DolphinDB查询性能测试用例

附录3. 内置函数计算性能测试用例

表10. InfluxDB内置函数计算性能测试用例

表11. DolphinDB内置函数计算性能测试用例

附录4. I/O性能测试程序

InfluxDBInsert.java:package test;

import org.influxdb.InfluxDB;

import org.influxdb.InfluxDBFactory;

import org.influxdb.dto.BatchPoints;

import org.influxdb.dto.Point;

import java.util.concurrent.TimeUnit;

public class InfluxDBInsert {

public static void main(String[] args) {

InfluxDBinfluxDB = InfluxDBFactory.connect("http://192.168.1.30:8086");

int size = 18314172;

long timer = 0;

for (int i = 0; i< size; i++) {

BatchPoints.BuilderbatchBuilder = BatchPoints.database("TEST");

for (int j = 0; j < 5000 &&i< size; i++, j++) {

Point.Builder builder = Point.measurement("TEST")

.time(System.nanoTime(), TimeUnit.NANOSECONDS)

.addField("Bid_Price", 2.5)

.addField("Bid_Size", 5)

.addField("Offer_Price", 12.5)

.addField("Offer_Size", 6)

.tag("Exchange", "B")

.tag("Sym", "ALV");

batchBuilder.point(builder.build());

}

long start = System.currentTimeMillis();

influxDB.write(batchBuilder.build());

timer += (System.currentTimeMillis() - start);

}

System.out.println(timer);

}

}

123456789101112131415161718192021222324252627282930313233

复制代码

DolphinDBInsert.java:package test;

import com.xxdb.DBConnection;

import com.xxdb.data.*;

import java.io.IOException;

import java.util.HashMap;

import java.util.Map;

public class DolphinDBInsert {

public static void main(String[] args) throws IOException {

int size = 18314172;

int range = 5000;

BasicLongVector Time = new BasicNanoTimestampVector(range);

BasicDoubleVectorBid_Price = new BasicDoubleVector(range);

BasicIntVectorBid_Size = new BasicIntVector(range);

BasicDoubleVectorOffer_Price = new BasicDoubleVector(range);

BasicIntVectorOffer_Size = new BasicIntVector(range);

BasicStringVector Exchange = new BasicStringVector(range);

BasicStringVector Symbol = new BasicStringVector(range);

DBConnection conn = new DBConnection();

conn.connect("192.168.1.30", 8888);

conn.run("if(existsDatabase('/home/psui/Desktop/workspace/data/NYSETAQ')){dropDatabase('/home/psui/Desktop/workspace/data/NYSETAQ')}");

conn.run("db = database('/home/psui/Desktop/workspace/data/NYSETAQ', RANGE, 0 5 10)");

conn.run("tbl = table(200:0,`Time`Bid_Price`Bid_Size`Offer_Price`Offer_Size`Exchange`Symbol,[NANOTIMESTAMP,DOUBLE,INT,DOUBLE,INT,STRING,SYMBOL])");

conn.run("Quotes = db.createPartitionedTable(tbl,'Quotes','Bid_Size')");

long timer = 0;

for (int i = 0; i< size; i++) {

if (i + 5000 >= size) {

Time = new BasicNanoTimestampVector(size-i);

Bid_Price = new BasicDoubleVector(size-i);

Bid_Size = new BasicIntVector(size-i);

Offer_Price = new BasicDoubleVector(size-i);

Offer_Size = new BasicIntVector(size-i);

Exchange = new BasicStringVector(size-i);

Symbol = new BasicStringVector(size-i);

for (int j = 0; i< size; i++, j++) {

Time.setLong(j, System.nanoTime());

Bid_Price.setDouble(j, 2.4);

Bid_Size.setInt(j, 6);

Offer_Price.setDouble(j, 3.5);

Offer_Size.setInt(j, 2);

Exchange.setString(j, "A");

Symbol.setString(j, "ALV");

}

} else {

for (int j = 0; j < 5000 &&i< size; i++, j++) {

Time.setLong(j, System.nanoTime());

Bid_Price.setDouble(j, 2.4);

Bid_Size.setInt(j, 6);

Offer_Price.setDouble(j, 3.5);

Offer_Size.setInt(j, 2);

Exchange.setString(j, "A");

Symbol.setString(j, "ALV");

}

}

Map map = new HashMap<>();

map.put("Time", Time);

map.put("Bid_Price", Bid_Price);

map.put("Bid_Size", Bid_Size);

map.put("Offer_Price", Offer_Price);

map.put("Offer_Size", Offer_Size);

map.put("Exchange", Exchange);

map.put("Symbol", Symbol);

long start = System.currentTimeMillis();

conn.upload(map);

conn.run("tbl = table(Time,Bid_Price,Bid_Size,Offer_Price,Offer_Size,Exchange,Symbol)");

conn.run("Quotes.append!(tbl)");

timer += (System.currentTimeMillis()-start);

}

conn.run("Quotee = loadTable(db, 'Quotes')");

Entity entity = conn.run("select count(*) from Quotee");

System.out.println(entity.getString());

System.out.println(timer);

}

}

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778

复制代码

数据导出:

InfluxDB:$ influx -host localhost -database Quotes -format csv -execute “” >Quotes.csv

1

复制代码

DolphinDB:saveText(Quotes, DATA_DIR + "/Quotes.csv")

1

复制代码

邮箱:info@dolphindb.com

influxdb与mysql的比较_DolphinDB与InfluxDB对比测试报告相关推荐

  1. telegraf监控mysql数据库_部署Telegraf+Influxdb+Grafana 架构来监控 MySQL

    前段时间小编写了一篇:使用Nginx+Telegraf+Influxb+Grafana构建高逼格Nginx集群监控系统!文章,详细了介绍了 采集器telegraf, 时序数据库influxdb , 数 ...

  2. influxdb常用命令、influxdb增删改查、SpringBoot整合influxdb

    influxdb常用命令.influxdb增删改查.SpringBoot整合influxdb 一.influxdb一些概念 1.时序数据库 2.influxdb和mysql类比 3.points(类似 ...

  3. linux下influxdb安装教程,Linux下安装使用InfluxDB

    安装: https://portal.influxdata.com/downloads/ 点击: 找到对应的系统版本,依次执行命令: wget https://dl.influxdata.com/in ...

  4. 【MySQl】MyISAM和InnoDB索引对比

    [MySQl]MyISAM和InnoDB索引对比 部分内容转自:http://www.2cto.com/database/201211/172380.html 比较好的文章:http://www.cn ...

  5. prometheus + influxdb + grafana + mysql

    2019独角兽企业重金招聘Python工程师标准>>> 前言 本文介绍使用influxdb 作为prometheus持久化存储和使用mysql 作为grafana 持久化存储的安装方 ...

  6. 4_InfluxDB学习之InfluxDB的基本概念、InfluxDB中独有的概念(Point,series),InfluxDB学习之InfluxDB的基本操作,InfluxDB操作方式,crud

    4.InfluxDB学习之InfluxDB的基本概念 4.1.与传统数据库中的名词做比较 4.2.InfluxDB中独有的概念 4.2.1.Point 4.2.2.series 4.3.InfluxD ...

  7. 如何修改influxdb表结构_使用nginx-lua修改influxdb API的返回结构

    有一个API平台服务,所有接口都通过API平台转发到实际的服务上,然后再把实际服务的结果返回给客户端,API平台的规范是所有实际服务的接口返回都要统一结构为 { "code": 0 ...

  8. influxdb无法查询tag_DolphinDB与InfluxDB对比测试报告

    DolphinDB是一款分析型的分布式时序数据库(time-series database),内置处理流式数据处理引擎,具有内置的并行和分布式计算的功能,并提供分布式文件系统,支持集群扩展.Dolph ...

  9. mysql filde_备份一个约250G的mysql实例【xtrabackup备份方案对比】

    备份一个约250G的mysql实例 A. 使用xtrabackup备份加gzip单线程压缩 time innobackupex --user=test --password=test  --socke ...

最新文章

  1. python中 __name__及__main()__的妙处02
  2. cdn贝免费套餐_阿里云香港服务器带宽太贵怎么办?香港节点全球CDN加速你值得拥有...
  3. 设计模式之装饰模式的学习
  4. 按主键更新另一个表oracle,SQL根据ID匹配从一个表更新到另一个表
  5. Oracle的Net Configuration Assistant 配置
  6. obj是什么数据类型 python_Python入门级第一天
  7. [论文阅读] Pyramid Feature Attention Network for Saliency Detection
  8. python turtle绕原点旋转_「加德老师与小朋友们的编程之旅」Python海龟作图(上)
  9. Codeforces 990G 点分治+暴力
  10. 让本地网络与微软windows azure互通
  11. 微信投票python脚本_微信投票python脚本
  12. win8 完全禁用uac的方法
  13. 高德地图JS-API开发—Marker添加及infoWindow处理
  14. 卸载CDH5.14.2
  15. 自己用命令强制删除占用的文件或文件夹
  16. 基于Flask的视频网站设计与实现(Python电影视频推荐系统)
  17. 网站防篡改有什么方法
  18. 图片心理性格测试
  19. 人工智能实战2019 第五次作业 焦宇恒 16721088
  20. 背完这10个经典面试答案,80%的面试都能喜提offer

热门文章

  1. java modbus lrc,C#实现modbus基于ASCII的LRC校验
  2. Vue中 模板template的四种写法
  3. 聚焦边缘计算场景,打造云边端一体化容器云平台
  4. cors 后端解决跨域问题
  5. 2021制定计划待办事项清单的记事便签
  6. 查看android手机arm版本
  7. 招聘求职小程序V4.1.87源码-修复后台里推广企业无法确认收益问题
  8. 香山里高手如云!(Writing)
  9. “华为杯”研究生数学建模竞赛2019年-【华为杯】A题:基于神经网络的无线电波传播损耗预测模型(附优秀论文及Python代码)
  10. python 开课_python全栈学习1.开课介绍