干货丨时序数据库DolphinDB与Spark的性能对比测试报告

1. 概述

Spark是基于内存计算的通用大数据并行计算框架,内置多种组件,如批处理、流处理、机器学习和图处理。Hive是基于Hadoop的数据仓库,支持类SQL的命令查询,提高了Hadoop的易用性。Spark与Hive、Hadoop一般是搭配使用,利用Hive中的数据分区能够方便地管理和过滤数据,提升查询效率。算法

DolphinDB是C++编写的高性能分布式时序数据库,内置高吞吐低延迟的列式内存引擎,集成了功能强大的编程语言,支持类Python和SQL的脚本语言,能够直接在数据库中进行复杂的编程和运算。DolphinDB内部用Data Source来抽象分区数据。在Data Source之上,能够完成SQL,机器学习,批处理和流处理等计算任务。一个Data Source既能够是内置的数据库分区,也能够是外部数据。若是Data Source是内置数据库的分区,大部分计算均可以在本地完成,极大地提高了计算和查询效率。数据库

本报告将对DolphinDB、Spark直接访问HDFS(Spark+Hadoop,下文称为Spark)、Spark经过Hive组件访问HDFS(Spark+Hive+Hadoop,下文称为Spark+Hive)三者进行性能对比测试。测试内容包括数据导入、磁盘空间占用、数据查询以及多用户并发查询。经过对比测试,咱们能更深刻的了解影响性能的主要因素,以及不一样工具的最佳应用场景。编程

2. 环境配置

2.1 硬件配置缓存

本次测试使用了两台配置彻底相同的服务器(机器1,机器2),各个配置参数以下:服务器

主机:DELL PowerEdge R730xd网络

CPU:Intel Xeon(R) CPU E5-2650 v4(24核 48线程 2.20GHz)并发

内存:512 GB (32GB × 16, 2666 MHz)app

硬盘:17T HDD (1.7T × 10, 222 MB/s 读取;210 MB/s 写入)框架

网络:万兆以太网机器学习

OS: CentOS Linux release 7.6.1810 (Core)

2.2 集群配置

测试的DolphinDB版本为Linux v0.95。测试集群的控制节点部署在机器1上,每台机器上各部署三个数据节点,共六个数据节点。每一个数据节点配置8个worker,7个executor,24G内存。

测试的Spark版本为2.3.3,搭载Apache Hadoop 2.9.0。Hadoop与Spark配置为彻底分布式模式,机器1为Master,而且在机器一、机器2上都具备Slave。Hive的版本是1.2.2,机器一、机器2上都具备Hive。元数据存储在机器1上的MySql数据库中。Spark 与Spark + Hive使用Standalone模式下的client 方式来提交应用。

测试时,DolphinDB、Spark、Spark+Hive均配置6块硬盘,不一样并发数下使用的CPU、内存总和都相同,都是48个线程,144G内存。Spark与Spark+Hive使用的资源只是对于特定的应用,每一个应用有6个executor,在多用户并发的状况下,Spark、Spark+Hive单个用户使用的资源会随着用户数量增多而减小。不一样并发数下每一个用户使用的资源如表1所示。

表1.Spark、Spark+Hive不一样并发数下单用户使用的资源

3. 数据集及数据库设计

3.1 数据集

测试数据集是纽约证券交易所(NYSE)提供的TAQ数据集,包含 8000 多支股票在2007.08.01-2007.08.31一个月内的Level 1报价数据,包含交易时间, 股票代码, 买入价, 卖出价, 买入量, 卖出量等报价信息。数据集中共有 65 亿(6,561,693,704)条报价记录,一个 CSV 中保存一个交易日的记录,该月共23个交易日,未压缩的 23个CSV 文件共计 277 GB。

数据来源:https://www.nyse.com/market-data/historical

3.2 数据库设计

表2. TAQ在各个系统中的数据类型。

在 DolphinDB database 中,咱们按照date、symbol列组合分区,第一分区使用日期DATE来进行值分区,共23个分区,第二分区使用股票代码SYMBOL来进行范围分区,分区数量100个,每一个分区大约120M左右。

Spark存储在HDFS上的数据以23个csv对应23个目录。Spark+Hive采用两层分区,第一层分区使用日期DATE列进行静态分区,第二层分区使用股票代码SYMBOL进行动态分区。

具体脚本见附录。

4. 数据导入和查询测试

4.1 数据导入测试

原始数据均匀地分布在两台服务器的6个硬盘上,这样能够充分利用集群中的全部资源。DolphinDB经过异步多节点的方式并行导入数据,Spark与Spark+Hive并行启动6个应用来读取数据,把数据存储到HDFS中。各个系统导入数据的时间如表3所示。各个系统中数据占用的磁盘空间如表4所示。数据导入脚本见附录。

表3. DolphinDB、Spark、Spark+Hive导入数据时间

表4. DolphinDB、Spark、Spark+Hive中数据占用的磁盘空间

DolphinDB的导入性能明显优于Spark和Spark+Hive,是Spark的4倍左右,是Spark + Hive的6倍左右。DolphinDB使用C++编写而且内部有不少优化,极大地利用了磁盘的IO。

DolphinDB占用的磁盘空间大于Spark与Spark+Hive,大约是他们的2倍,这是由于Spark和Spark+Hive在Hadoop上都使用Parquet格式,Parquet格式经过Spark写入到Hadoop上默认使用snappy压缩。

4.2 数据查询测试

为保证测试公平,每一个查询语句要进行屡次测试,每次测试以前均经过 Linux 系统命令分别清除系统的页面缓存、目录项缓存和硬盘缓存。DolphinDB还清除其内置缓存。

表5中的查询语句涵盖了大部分查询场景,包含分组、排序、条件、聚合计算、点查询、全表查询,用来评估DolphinDB、Spark、Spark+Hive在不一样用户数量提交下的性能。

表5. DolphinDB、Spark、Spark+Hive查询语句

4.2.1 DolphinDB与Spark单用户查询测试

如下是DolphinDB与Spark单用户查询的结果,结果中的耗时为查询8次的平均用时。

表6. DolphinDB、Spark单用户查询结果

从结果能够看出,DolphinDB的查询性能是Spark+HDFS的200倍左右。查询Q1到Q6都是以DolphinDB的分区字段为过滤条件,DolphinDB只须要加载指定分区的数据,无需全表扫描,而Spark从Q1到Q6都须要全表扫描,耗费大量的时间。对于查询Q7,DolphinDB和Spark都须要全表扫描,可是DolphinDB只加载相关的列,无需加载全部列,而Spark则须要加载全部数据。因为Query运行时间被数据加载主导,DolphinDB和Spark的性能差距没有以前的查询语句的大。

4.2.2 DolphinDB与Spark+Hive单用户查询测试

因为DolphinDB的数据通过分区,且在查询的时候实现谓词下推,效率明显高于Spark。此处咱们使用Spark搭载Hive组件来访问HDFS,对比DolphinDB和Spark+Hive的查询性能。如下是DolphinDB、Spark+Hive单用户查询的结果,结果中的耗时为查询8次的平均用时。

表7. DolphinDB、Spark+Hive单用户查询结果

结果显示,DolphinDB的查询性能明显优于Spark+Hive,是Spark+Hive的数十倍。与表6的结果相比,Spark+Hive的查询速度比Spark要快得多,DolphinDB具备的优点明显降低了不少。这是由于Hive对数据进行分区,且在查询语句的条件带有分区字段的时候,只加载部分数据,实现数据过滤,提升效率。查询语句Q7扫描全表的时候会出现内存溢出。

DolphinDB、Spark+Hive都对数据进行了分区,且在加载数据时均可以实现谓词下推,达到数据过滤的效果,可是DolphinDB的查询速度优于Spark+Hive。这是由于Spark+Hive区读取HDFS上的数据是不一样系统之间的访问,数据要通过序列化、网络传输、反序列化的过程,很是耗时,从而影响性能。DolphinDB的大部分计算都在本地完成,减小了数据传输,所以更加高效。

4.2.3 DolphinDB与Spark计算能力对比

上面DolphinDB分别与Spark、Spark+Hive的查询性能对比,因为数据分区、查询时的数据过滤以及传输影响了Spark的性能,所以这里咱们先把数据加载到内存中,再进行相关的计算,比较DolphinDB和Spark+Hive。咱们省略了Spark+Hive,由于使用Hive只是为了数据过滤,读取HDFS上的数据更加高效,这里的测试数据已经在内存中。

表8是测试计算能力的语句。每次测试都包含两个语句,第一个语句是把数据加载到内存中,第二个语句是对内存中的数据进行计算。DolphinDB会自动缓存数据,Spark则经过本身的默认缓存机制从新建立一个临时表TmpTbl。

表8. DolphinDB与Spark计算能力对比语句

如下是DolphinDB与Spark计算能力的测试结果,结果中的耗时是测试5次的平均用时。

表9. DolphinDB与Spark计算能力测试结果

因为数据已经在内存中,对比表6,Spark使用的时间大幅度减小,可是DolphinDB的计算能力仍然比Spark优越。DolphinDB用C++编写,本身管理内存,比起Spark使用JVM来管理内存更加高效。另外,DolphinDB内置了更高效的算法,提升了计算性能。

DolphinDB的分布式计算以分区为单位,计算指定内存的数据。Spark加载整个HDFS上的块,一个数据块包含了具备不一样symbol值的数据,虽然缓存,可是仍然要筛选,因此在Q1与Q2的比值较大。Spark计算时使用的广播变量是通过压缩的,传输到其余的executor上再解压影响性能。

4.2.4 多用户并发查询

咱们使用表5中的查询语句,对DolphinDB、Spark、Spark+Hive进行多用户并发查询测试。如下是测试结果,结果中的耗时是查询8次的平均用时。

表10. DolphinDB、Spark、Spark+Hive多用户并发查询结果

图1. DolphinDB、Spark多用户查询结果对比

图2. DolphinDB、Spark+Hive多用户查询结果对比

从上面的结果能够看出,随着并发数量的增长,三者的查询时间逐渐增长。当达到8个用户并发的时候Spark性能较以前少许的用户并发状况下显著降低,Spark 在执行Q7的时候会致使worker死亡。Spark+ Hive在多用户访问的时候与DolphinDB同样,基本保持稳定,可是执行Q7查询语句的一直会出现内存溢出的异常。

Spark+ Hive的查询配置与Spark 同样,由于有分区的做用,而且能够过滤数据,查询数据量比较小,因此效率相对于Spark扫描所有数据比较好。

DolphinDB在并发查询中性能明显优于Spark 与Spark+ Hive,从上图能够看出在多用户并发访问状况下,随着用户数量的增长,DolphinDB相对于Spark 的优点几乎是线性增加,相对于Spark + Hive 的优点基本保持不变,体现了有数据分区在查询的时候实现数据过滤的重要性。

DolphinDB在多用户并发的状况下实现了多用户的数据共享,不像Spark 的数据只是针对于具体的应用。因此在8个并发用户的状况下,Spark 每一个用户分配到的资源比较少,性能显著降低。DolphinDB的数据共享能够减小资源的使用,在有限的资源下,把更多的资源留给用户计算使用,提升用户并发的效率,增大用户的并发数量。

5. 小结

在数据的导入方面,DolphinDB能够并行加载,Spark与Spark+Hive 则经过多个应用同时加载来导入数据。DolphinDB的导入速度是Spark 和Spark+ Hive 的4-6倍。在磁盘空间上,DolphinDB占用的磁盘空间是Spark与Spark+ Hive在Hadoop上占用的磁盘空间的两倍左右,Spark与Spark + Hive使用了snappy压缩。

在数据的SQL查询方面,DolphinDB的优点更加明显。优点主要来自四个方面:(1)本地化计算,(2)分区过滤,(3)优化的内存计算,(4)跨会话的数据共享。在单用户查询状况下,DolphinDB的查询速度是Spark的几倍到上百倍,是Spark+ Hive 的几十倍。Spark 读取HDFS 是不一样的系统之间的调用,其中包含了数据的序列化,网络,反序列化很是消耗时间,且占据不少的资源。DolphinDB的SQL查询大部分是本地化计算,大幅减小了数据传输和加载的时间。Spark+ Hive 相对与Spark速度提高很大,主要是由于Spark + Hive只扫描相关分区的数据,实现了数据的过滤。在剔除本地化和分区过滤的因素后(即全部数据已经在内存中),DolphinDB的计算能力仍然优于Spark数倍。DolphinDB基于分区的分布式计算效率很高,且对内存的管理比Spark基于JVM的管理更加优秀。Spark的多用户并发会随着用户数量的增多效率逐渐降低,在查询大数据量的时候用户过多致使worker 死亡。Spark + Hive的多用户并发相对比较稳定,可是加载数据过大会出现内存溢出错误。 多用户状况下, DolphinDB能够实现数据的共享,从而减小加载数据使用的资源,查询速度是Spark的数百倍,是Spark+Hive 的几十倍。随着用户数量的增长,DolphinDB相对于Spark的性能优点更加明显。涉及到分区查询的状况下,Spark+ Hive与DolphinDB显著提升查询性能。

Spark是一个很是优秀的通用分布式计算引擎,在SQL查询、批处理、流处理、机器学习等方面均有上佳表现。但因为SQL查询一般只须要对数据计算一次,相对于机器学习须要上百次的迭代,内存计算的优点没法充分体现。所以,咱们更建议将Spark用于计算密集型的机器学习。

在测试过程当中,咱们也发现DolphinDB是一个很是轻量级的实现,集群的搭建简单快速, Spark + Hive+ Hadoop 集群安装配置很是复杂。

附录

附录1. 数据预览

附录2. Hive建立表语句

CREATE TABLE IF NOT EXISTS TAQ (time TIMESTAMP, bid DOUBLE, ofr DOUBLE, bidsiz INT, ofrsiz INT, mode INT, ex TINYINT, mmid STRING)PARTITIONED BY (date DATE, symbol STRING) STORED AS PARQUET;

附录3.

DolphinDB导入数据脚本:

fps一、fps2分别表明机器一、2上全部的csv路径的vector
fps是包含fps1和fps2 的vector
allSites一、allSites2 分别表明机器一、2上数据节点名称的vector
allSite 是包含 allSites1和allSites2的vector
DATE_RANGE=2007.07.01..2007.09.01
date_schema=database('', VALUE, DATE_RANGE)
symbol_schema=database('', RANGE, buckets)
db=database(FP_DB, COMPO,[date_schema,symbol_schema])
taq = db.createPartitionedTable(schema, `taq, `date`symbol)
for(i in 0..1){
	for(j in 0..(size(fps[i])-1))  {
		rpc(allSites[i][j] % size(allSite[i])],submitJob,"loadData" , "loadData" ,loadTextEx{database(FP_DB), "taq", `date`symbol, fps[i][j]} )
	}
}

Spark与Hive导入数据的配置:

--master local[8]
--executor-memory 24G
相关文章
相关标签/搜索