金融市场高频数据应当如何管理——DolphinDB与pickle的性能对比测试和分析

2022-03-28 00:00:00 数据 节点 缓存 测试 耗时

金融市场L1/L2的报价和交易数据是量化交易研究非常重要的数据。国内全市场L1/L2的历史数据约为20~50T,每日新增的数据量约为20~50G。传统的关系数据库如MS SQL Server或MySQL均无法支撑这样的数据量级,即便分库分表,查询性能也远远无法达到要求。例如Impala和Greenplum的数据仓库,以及例如HBase的NoSQL数据库,可以解决这个数据量级的存储,但是这类通用的存储引擎缺乏对时序数据的友好支持,在查询和计算方面都存在严重的不足,对量化金融普遍采用的Python的支持也极为有限。

数据库的局限性使得一部分用户转向文件存储。HDF5,Parquet和pickle是常用的二进制文件格式,其中pickle作为Python对象序列化/反序列的协议非常高效。由于Python是量化金融和数据分析的常用工具,因此许多用户使用pickle存储高频数据。但文件存储存在明显的缺陷,譬如大量的数据冗余,不同版本之间的管理困难,不提供权限控制,无法利用多个节点的资源,不同数据间的关联不便,数据管理粒度太粗,检索和查询不便等等。

目前,越来越多的券商和私募开始采用高性能时序数据库DolphinDB来处理高频数据。DolphinDB采用列式存储,并提供多种灵活的分区机制,可充分利用集群中每个节点的资源。DolphinDB的大量内置函数对时序数据的处理和计算非常友好,解决了传统关系数据库或NoSQL数据库处理时序数据方面的局限性。使用DolphinDB处理高频数据,既可以保证查询与计算的超高性能,又可以提供数据管理、权限控制、并行计算、数据关联等数据库的优势。

本文测试DolphinDB和pickle在数据读取方面的性能。与使用pickle文件存储相比,直接使用DolphinDB数据库,数据读取速度可多可提升10倍以上;若为了考虑与现有Python系统的集成,使用DolphinDB提供的Python API读取数据,速度多有2~3倍的提升。有关DolphinDB数据库在数据管理等方面的功能,读者可参考DolphinDB的在线文档或教程。

  • 1. 测试场景和测试数据
  • 2. 测试环境
  • 3. 测试方法
    • 3.1 测试DolphinDB
    • 3.2 测试DolphinDB的Python API
    • 3.3 测试pickle文件
  • 4. 测试结果分析
    • 4.1 DolphinDB的性能优势来源
    • 4.2 字符串对性能的影响
    • 4.3 多任务并发下的性能对比
  • 5. 库内分析的必要性
  • 6. 结论和展望

1. 测试场景和测试数据

本次测试使用了以下两个数据集。

  • 数据集1是美国股市一天(2007.08.23) Level 1的报价和交易数据。该数据共10列,其中2列是字符串类型,其余是整型或浮点数类型,存储在dolphindb中的表结构如下表,一天的数据约为2亿3000万行。csv文件大小为9.5G,转换为pickle文件后大小为11.8G。
列名类型
symbolSYMBOL
dateDATE
timeSECOND
bidDOUBLE
ofrDOUBLE
bidsizINT
ofrsizINT
modeINT
exCHAR
mmidSYMBOL
  • 数据集2是中国股市3天(2019.09.10~2019.09.12)的Level 2报价数据。数据集总共78列,其中2列是字符串类型,存储在dolphindb中的表结构如下表,一天的数据约为2170万行。一天的csv文件大小为11.6G,转换为pickle文件后大小为12.1G。
列名类型列名类型
UpdateTimeTIMETotalBidVolINT
TradeDateDATEWAvgBidPriDOUBLE
MarketSYMBOLTotalAskVolINT
SecurityIDSYMBOLWAvgAskPriDOUBLE
PreCloPriceDOUBLEIOPVDOUBLE
OpenPriceDOUBLEAskPrice1~10DOUBLE
HighPriceDOUBLEAskVolume1~10INT
LowPriceDOUBLEBidPrice1~10DOUBLE
LastPriceDOUBLEBidVolume1~10INT
TradNumberINTNumOrdersB1~10INT
TradVolumeINTNumOrdersS1~10INT
TurnoverDOUBLELocalTimeTIME


DolphinDB database的数据副本数设为2。将这两个数据集写入DolphinDB后,磁盘占用空间为10.6G,单份数据仅占用5.3G,压缩比约为8:1。pickle文件没有采用压缩存储。测试发现pickle文件压缩后,加载时间大幅延长。

对比测试查询一天的数据。对DolphinDB Python API与pickle,记录从客户端发出查询到接收到数据并转换成Python pandas的DataFrame对象的耗时。

  • 对于DolphinDB Python API,整个过程包括三个步骤:(1)从DolphinDB数据库查询数据耗时,即若不使用Python API而直接使用DolphinDB查询所需耗时;(2)把查询到的数据从DolphinDB数据节点发送到python API客户端需要的时间;(3) 在客户端将数据反序列化成pandas DataFrame需要的时间。
  • 对于pickle,耗时为使用pickle模块加载pickle数据文件所需要的时间。

2. 测试环境

测试使用的三台服务器硬件配置如下:

主机:PowerEdge R730xd

CPU:E5-2650 24cores 48线程

内存:512G

硬盘:HDD 1.8T * 12

网络:万兆以太网

OS:CentOS Linux release 7.6.1810

本次测试使用的是DolphinDB多服务器集群模式。共使用3台服务器,每台服务器部署2个数据节点,每个节点分配2个10K RPM的HDD磁盘,内存使用限制为32G,线程数设置为16。数据库的副本数设置为2。测试的客户机安排在其中的一台服务器上。

本次测试的DolphinDB服务器版本是1.30.0,Python API for DolphinDB的版本是1.30.0.4。

3. 测试方法

读写文件之后,操作系统会缓存相应的文件。从缓存读取数据,相当于从内存读取数据,这会影响测试结果。因此每一次测试前,都会清除操作系统的缓存和DolphinDB 的缓存。为了对比,也测试有缓存时的性能,即不存在磁盘IO瓶颈时的性能。

3.1 测试DolphinDB

测试代码如下:

#读取Level 1数据集一天的数据
timer t1 = select * from loadTable("dfs://TAQ", "quotes") where TradeDate = 2007.08.23

#读取Level 2数据集一天的数据
timer t2 = select * from loadTable("dfs://DataYesDB", "tick") where TradeDate = 2019.09.10

相关文章