共计 8461 个字符,预计需要花费 22 分钟才能阅读完成。
DolphinDB 和 MongoDB 都是为大数据而生的数据库。然而两者有这较大的区别。前者是列式存储的多模型数据库,次要用于结构化时序数据的高速存储、查问和剖析。后者是文档型的 NoSQL 数据库,可用于解决非结构化和结构化的数据,能够依据键值疾速查找或写入一个文档。MongoDB 有着本人最合适的利用场景。然而市场上短少优良的大数据产品,不少用户试图应用 MongoDB 来存储和查问物联网和金融畛域的结构化时序数据。本测试的目标是评估 MongoDB 是否适宜此类海量时序数据集。
1. 测试环境
本次测试在单机上进行,测试设施配置如下:
主机:DELL OptiPlex 7060
CPU:Intel(R) Core(TM) i7-8700 CPU@3.20GHZ,6 核 12 线程
内存:32 GB (8GB x 4, 2,666 MHz)
硬盘:2T HDD (222MB/ s 读取;210MB/ s 写入)
OS:Ubuntu 18.04 LTS
DolphinDB 选用 Linux0.89 作为测试版本,所有节点最大连接数为 128,数据正本设置为 2,设置 1 个管制节点,1 个代理节点,3 个数据节点。
MongoDB 选用 Linux4.0.5 社区版作为测试版本,shard 集群线程数为 12,所有服务器的最大连接数均为 128。MongoDB 的 shard 集群设置为 1 个 config 服务器,1 个 mongos 路由服务器,3 个分片服务器,其中 config 服务器设置为有 1 个主节点和 2 个从节点的 replica 集群,3 个分片服务器均设置为有 1 个主节点,1 个从节点,1 个仲裁节点的 replica 集群。DolphinDB 和 MongoDB 的参数配置请参考附录 1。
2. 数据集
本报告测试了 DolphinDB 和 MongoDB 在小数据量级(4.2GB)和大数据量级(62.4GB)下的性能。
对于大小两种数据集,咱们测试两种数据库在磁盘分区状况下的性能,查问工夫均蕴含了磁盘 IO 的工夫。为了保障测试的偏心,咱们在测试前通过 linux 命令:sync,echo1,2,3 | tee /proc/sys/vm/drop_caches 清空页面缓存,目录缓存和硬盘缓存,随后顺次执行 13 条查问,并记录执行的工夫。
以下是两个数据集的表构造和分区办法:
设施传感器信息小数据集(CSV 文件,4.2G, 3 千万条数据)
咱们选用 TimescaleDB 官网提供的 devices_readings_big.csv(以下简称 readings 数据集)和 device_info_big.csv(以下简称 info 数据集)设施传感器数据作为小数据测试集。readings 数据集蕴含 3,000 个设施在 10,000 个工夫距离(2016.11.15-2016.11.19)上的传感器信息,包含传感器工夫,设施 ID,电池,内存,CPU 等时序统计信息。info 数据集包含 3,000 个设施的设施 ID,版本号,制造商,模式和操作系统等统计信息。
数据起源:https://docs.timescale.com/v1.1/tutorials/other-sample-datasets
数据集共 3 千万 条数据(4.2G),压缩包内蕴含一张设施信息表和一张设施传感器信息记录表,表构造以及分区形式如下:
readings 数据集
info 数据集
数据集中 device_id 这一字段有 3000 个不同的值,且在 readings 数据集中反复呈现,这种状况下应用 string 类型不仅占用大量空间而且查问效率低,DolphinDB 的 symbol 类型能够很好地解决占用空间和效率两个问题。
咱们在 DolphinDB database 中采纳组合分区,将 time 字段作为分区的第一个维度,按天分为 4 个区,再将 device_id 作为分区的第二个维度,每天一共分 10 个区,最初每个分区所蕴含的原始数据大小约为 100MB。
咱们在 MongoDB 中同样采纳组合分区的形式,将 time 作为分区的第一维度,依据日期进行范畴分区,再将设施 ID 作为第二分区维度,依据设施 ID 进行范畴分区。MongoDB 的范畴分区是依据块的大小进行分区的,当数据块大小大于某个阈值,数据库会主动将一个大的数据块分为两个小的数据块,实现分区。通过测试,咱们发现当 chunkSize(数据块分区阈值)为 1024 时,性能最佳。最终,readings 数据集总共分为 17 个分区。
MongoDB 要求分区字段必须建设索引,因而咱们建设日期 + 设施 ID 的复合索引,复合索引能够放慢查问速度,然而 MongoDB 在建设索引时会耗费工夫和空间。readings 数据集分区建设 time_1_device_id_1 增序索引耗时为 5 分钟,占用空间大小为 1.1G。建设索引的脚本如下所示:
use device_pt
db.device_readings.createIndex({time:1,device_id:1}
股票交易大数据集(CSV 文件,62.4G,16 亿条数据)
咱们选用纽约证券交易所(NYSE)提供的 2007.08.07-2007.08.10 四天的股市 Level1 报价数据(以下简称 TAQ 数据集)作为大数据测试集,数据集蕴含 8,000 多支股票在 4 天内的交易工夫,股票代码,买入价,卖出价,买入量,卖出量等报价信息。
数据集有 4 个 csv 文件,每个文件在 14G 到 17G 之间,总共大小为 62.4G,大概 16 亿条数据,每个 CSV 文件保留一个交易日的交易信息,数据来源于(https://www.nyse.com/market-data/historical)。TAQ 数据集构造如下所示:
在 DolphinDB 中,咱们采纳组合分区,将 date 字段作为分区的第一维度,每天一个分区,共四个分区,再将 symbol 字段作为分区的第二维度,依据范畴分区,每天分为 100 个分区。最初总共分为 400 个分区,每个分区大概 40MB。
在 MongoDB 中同样采纳组合分区形式,分区维度与 DolphinDB 雷同,将 chunkSize 设置为 1024,总共分为 385 个分区。
MongoDB 在对 TAQ 数据集分区时建设 date_1_symbol_1 增序索引耗费的工夫为 53 分钟,占用空间大小为 19G,建设索引的脚本如下所示:
use taq_pt_db
db.taq_pt_col.createIndex({date:1,symbol:1}
3. 数据库导入导出性能比照
3.1 导入性能
在 DolphinDB 中应用以下脚本导入:
timer {for (fp in fps) {job_id_tmp = fp.strReplace(".csv", "")
job_id_tmp1=split(job_id_tmp,"/")
job_id=job_id_tmp1[6]
job_name = job_id
submitJob(job_id, job_name, loadTextEx{db, `taq, `date`symbol, fp})
print now() + ": 已导入" + fp}
getRecentJobs(size(fps))
}
在 MongoDB 导入 TAQ 数据集时,为了放慢导入速度,将 63G 的数据分为 16 个小文件导入,每个文件大小在 3.5G~4.4G 之间,而后应用以下脚本导入:
for f in /media/xllu/aa/TAQ/mongo_split/*.csv ; do
/usr/bin/mongoimport
-h localhost
--port 40000
-d taq_pt_db
-c taq_pt_col
--type csv
--columnsHaveTypes
--fields "symbol.string(),date.date(20060102),time.date(15:04:05),bid.double(),ofr.double(),bidsiz.int32(),ofrsiz.int32(),mode.int32(),ex.string(),mmid.string()"
--parseGrace skipRow
--numInsertionWorkers 12
--file $f
echo "文件 $f 导入实现"
done
导入性能如下表所示:
从上表可得,DolphinDB 在导入结构化的时序数据时,速度远快于 MongoDB,上面从几个方面剖析导入后果。
(1)横向比拟
因为两个数据集的字段数量和字段类型不一样,readings 数据集多为字符串类型,TAQ 数据集多为数值类型,相比于字符串类型,数值类型导入更快,因而能够看到 MongoDB 和 DolphinDB 在导入 TAQ 数据集时,速率更快。
(2)纵向比拟
MongoDB 属于文档型数据库,导入速度受文档数量的影响很大,能够看出导入 3 千万条记录大概需 1 小时,导入 16 亿条记录大概需 55 小时,记录条数相差大概 53 倍,导入工夫相差约 55 倍,思考到每条记录字段类型和数据的影响,能够认为导入速度和记录条数大概成正比。
DolphinDB 属于列式数据库,存储这种结构化的数据时,DolphinDB 会将一个字段当成一个列,存储在一个列文件中。导入 readings 数据集时创立了 12 个列文件,导入 TAQ 数据集时,创立了 10 个列文件,列文件数量相差不多。导入 4.2G 数据,须要 63 秒,导入 62.4G 数据,须要 11 分 30 秒。数据集大小相差大概 14.8 倍,导入工夫相差大概 11 倍,思考到列文件数量和存储类型的不同,能够认为导入工夫和文件大小大概成正比。
DolphinDB 在导入时序结构化数据时,在列字段类型和数量相差不大的状况下,导入工夫和文件大小成正相干,合乎列式存储数据库的特点。MongoDB 在导入时序结构化数据时,在字段相差不大的状况下,导入工夫和记录条数成正相干,合乎文档型存储数据库的特点。
(3)MongoDB 导入绝对迟缓的起因剖析
DolphinDB 采纳列式存储,效率远远高于 MongoDB 的文档型存储。MongoDB 依照记录逐条导入,在记录条数很大的状况下,MongoDB 数据导入时长减少,性能降落。
MongoDB 在 sharding 集群配置时,必须开启 journaling 日志,先写入记录再进行导入操作,升高了其导入速度。
因为 MongoDB 属于 NoSQL 数据库,其没有主键概念,为了保障唯一性束缚,数据在导入时必须创立一个数据库主动生成的惟一索引来表征每一条记录,数据导入和索引必须同时进行,因而升高了导入速度。
3.2 导出性能
在 DolphinDB 中应用以下脚本进行数据导出:
timer saveText((select * from t),"/media/xllu/aa/device/device_readings_out.csv")
在 MongoDB 中应用以下脚本进行数据导出:
mongoexport -h localhost:40000 -d db_nopt -c device_readings -o /media/xllu/aa/device/
device_readings_mongo_out.csv
小数据集导出性能如下表所示:
4. 数据库磁盘空间占用比照
数据库磁盘空间占用性能比照次要比照 DolphinDB 和 MongoDB 数据库导入 readings 数据集和 TAQ 数据集这两种大小的数据集后,在分区状况下各数据库中的数据所占磁盘空间的大小。磁盘占用指标为数据在磁盘中的大小。
DolphinDB 间接通过读取所有列式数据文件的大小获取,MongoDB 通过 db.stats()取得数据存储的大小。两个数据库均有一个备份,MongoDB 中数据存储大小还包含索引的大小。测试后果如下表所示:
雷同数据量,MongoDB 的磁盘占用空间大概是 DolphinDB 的 2~3 倍,次要有以下起因:
(1)DolphinDB 采纳列式存储形式,每个列有固定的类型,通过 LZ4 压缩算法,将每个字段依照类型压缩存储为一个列文件。并且针对 symbol 类型,还采纳位图压缩算法解决存储空间占用的问题,进一步提高了压缩率。MongoDB 本次测试采纳的是 WiredTiger 存储引擎,选用 snappy 压缩算法。
(2)MongoDB 中建设分区数据库均要对分区字段建设索引,进一步导致其存储空间变大,经剖析发现,readings 数据集对 time 和 device_id 字段建设的索引大小为 1.1G,TAQ 数据集对 date 和 symbol 字段建设的索引大小为 19G。
5. 数据库查问性能
对于 readings 数据集和 TAQ 数据集,咱们比照了以下 8 种罕用的 SQL 查问。
1、点查问:依据某一字段的具体值进行查问。
2、范畴查问:依据一个或者多个字段的范畴依据工夫区间进行查问。
3、聚合查问:依据数据库提供的针对字段列进行计数,平均值,求和,最大值,最小值,标准差等聚合函数进行查问。
4、精度查问:依据不同标签维度列进行数据聚合,实现高维或者低维的字段范畴查问,测试有 hour 精度,minute 精度。
5、关联查问:依据不同的字段,在进行雷同精度,雷同的工夫范畴内进行过滤查问的根底上,筛选出有关联关系的指标列并进行分组。
6、比照查问:依据两个维度将表中某字段的内容重新整理为一张表格(第一维度作为列,第二维度作为行)
7、抽样查问:依据数据库提供的数据采样 API,能够为每一次查问手动指定采样形式进行数据的稠密解决,避免查问工夫范畴太大数据量过载的问题。
8、经典查问:理论业务中罕用的查问。
执行工夫是以毫秒为单位的。为了打消网络传输等不稳固因素的影响,查问性能比拟的工夫指标为服务器执行某个查问的工夫,不包含后果传输和显示的工夫。
4.2G 设施传感器信息小数据集查问测试
对于小数据集的测试,咱们均测试磁盘分区数据,执行工夫包含了磁盘 IO 的工夫。为了保障测试的准确性和公正性,每次启动测试前均通过 Linux 系统命令 sync;echo 1,2,3 | tee /proc/sys/vm/drop_caches 革除零碎的页面缓存,目录项缓存和硬盘缓存,启动程序后一次执行样例一遍,并记录执行的工夫。
DolphinDB 中应用以下脚本失去数据库句柄:
dp_readings = "dfs://db_range_dfs"
device_readings=loadTable(dp_readings, `readings_pt)
MongoDB 中执行 use device_pt 语句切换数据库至 device_pt 数据库。在执行关联查问时,因为 info 数据集的数据量较小,因而能够把数据加载到内存中。在 MongoDB 中执行 db.device_info.find({})将 3,000 条设施记录全副加载,在 DolphinDB 中执行 loadText(dp_info)将 3,000 条设施记录加载至内存。在 DolphinDB 中应用 timer 计算查问执行耗时,在 MongoDB 中应用 explain()函数获取执行工夫。上面是 DolphinDB 在小数据集上的查问脚本,MongoDB 的查问脚本见附录。
查问性能如下表所示:
对于范畴查问,在包含了分区字段的查问中,如查问 3,4 所示,MongoDB 能够调用复合索引,DolphinDB 能够通过分区字段放慢查问,这种状况下两个数据库的差距在 4 倍之内,并不是很大。在包含了未分区字段的查问中,如查问 5 所示,MongoDB 没法调用未分区字段的索引,须要进行全字段搜寻过滤,DolphinDB 则无需搜寻不在 where 过滤条件中的字段,这种状况下 DolphinDB 和 MongoDB 的差距进一步扩充。能够看出在解决这种结构化时序数据时,DolphinDB 采取的列式存储的形式的效率比 MongoDB 建设索引的形式更加高效,也更加实用于多维结构化数据的查问。
对于点查问 ,在查问 1 中,MongoDB 在建设有 time+device_id 索引的状况下能够疾速的找到某个工夫点的记录,DolphinDB 中依照日期分为 4 天,查找某一天的具体的工夫点须要选定一个分区再进行检索,这种状况下 DolphinDB 比 MongoDB 慢。在查问 2 中,MongoDB 的过滤字段仅为设施 ID,没有包含 time 字段,咱们从 explain() 中发现查问过程中没有调用复合索引,这是因为查问字段必须包含复合索引的首字段,索引才会起作用,查问 1 仅仅依据设施 ID 过滤,不波及 time 字段的过滤,MongoDB 不会调用复合索引,因而这种状况下,DolphinDB 比 MongoDB 快。
对于关联查问,MongoDB 作为 NoSQL 数据库,仅反对左外连贯,并且因为其没有关系型数据库的主键束缚,要实现表连贯查问只能应用内嵌文档的形式,这种形式并不利于计算和聚合。DolphinDB 作为关系型数据,其反对等值连贯,左连贯,全连贯,asof 连贯,窗口连贯和穿插连贯,表连贯查问功能丰富,能够高效不便地解决海量结构化时序数据。从查问 9~10 中咱们能够看出 DolphinDB 快于 MongoDB,并且关联查问越简单,性能差距越大。
对于抽样查问,MongoDB 能够在 aggregation 函数中通过 sample 语句实现抽样查问,抽样形式取决于汇合的大小,N(抽样数)的大小和 sample 语句实现抽样查问,抽样形式取决于汇合的大小,N(抽样数)的大小和 sample 语句在 pipeline 中的地位。DolphinDB 不反对全表抽样,仅反对分区字段抽样。因为两种数据抽样查问的实现过程差异较大,所以不做比拟。
对于插值查问,MongoDB 并没有内置的函数能够实现插值查问,而 DolphinDB 反对 4 种插值形式,ffill 向后取非空值填充、bfill 向前去非空值填充、lfill 线性插值、nullFill 指定值填充。
对于比照查问,MongoDB 作为文档型数据库,其存储单元是文档,汇合中蕴含若干文档,文档采纳 BSON 格局,没有行和列的概念,因而无奈实现抉择两个维度将表中某字段的内容整顿为一张表(第一个维度作为列,第二个维度作为行)的性能。DolphinDB 中内置有 pivot by 函数语句,选定分类的维度能够不便的将制订内容整顿为一张表。因为 MongoDB 不反对比照查问,所以不做比拟。
62.4G 股票交易大数据集查问测试
DolphinDB 中应用以下脚本失去数据库句柄:
taq_pt_db= "dfs://db_compound_dfs"
taq_pt_col=loadTable(taq_pt_db, `readings_pt)
MongoDB 中执行 use taq_pt_db 语句切换数据库至 taq_pt_db 数据库。
大数据集 DolphinDB 的查问脚本如下所示:
查问性能如下表所示:
在大数据量,两个数据库均做了分区的状况下,DolphinDB 仍然比 MongoDB 大概快 5 -20 倍。查问 1 是依据日期,股票代码进行的点查问,这种状况下 MongoDB 和 DolphinDB 的性能差距不大,DolphinDB 略慢于 MongoDB,这是 MongoDB 进行复合分区时会建设 date+symbol 复合索引能够较为疾速的找到后果,是 MongoDB 比拟好的利用场景,然而比照查问 5~9 可知,MongoDB 的计算性能仍不如 DolphinDB,差距大概在 10-20 倍之间。
6. 小结
工夫序列数据库 DolphinDB 和 MongoDB 在时序数据库集上的比照测试,次要论断如下:
- DolphinDB 的数据导入速度比 MongoDB 高出两个数量级。数据量越大,性能差距越显著。数据导出方面,DolphinDB 比 MongoDB 快 50 倍左右。
- 磁盘空间占用方面,MongoDB 占用磁盘是 DolphinDB 的 2~3 倍。
- 数据库查问性能方面,DolphinDB 在 4 个查问性能测试中速度比 MongoDB 快 30 倍;在 5 个查问性能测试中速度比 MongoDB 快 10~30 倍;在 12 个查问性能测试中速度比 MongoDB 快数倍;仅在两个点查问测试中,DolphinDB 慢于 MongoDB。
在解决结构化的时序数据时,无论是数据导入导出、磁盘空间占用还是查问速度,DolphinDB 的性能都比 MongoDB 更加优越。然而,MongoDB 作为文档型的 NoSQL 数据库,在数据模型多变的场景下以及解决非结构化数据方面更有劣势。
附录
1. DolphinDB 环境配置
- controller.cfg
- agent.cfg
- cluster.cfg
- cluster.nodes
2. MongoDB 环境配置
-
分片服务器配置:
- 主节点:master_shard.txt
- 从节点:slave_shard.txt
- 仲裁节点:arbiter_shard.txt
- 路由服务器配置:master_mongos.txt
-
配置服务器:
- 主节点:master_config.txt
- 从节点:slave_config.txt
- 仲裁节点:arbiter_config.txt
3. DolphinDB 分区脚本
- readings 分区脚本
- TAQ 分区脚本
4. MongoDB 分区脚本
- readings 分区脚本
- TAQ 分区脚本
5. MongoDB 查问脚本
- readings 查问脚本
- TAQ 查问脚本