3、数据存储设计:HDF5、Parquet、SQLite存储方案对比,时间序列数据库选型

做订单簿回溯,数据存储这块儿,说实话,我踩过的坑比赚到的钱还多。

一开始我图省事,直接往CSV里怼。结果呢?一个月的Level2数据,文件几十个G,加载一次要等一首歌的时间。后来我学乖了,开始认真研究存储方案。

今天咱们就聊聊,订单簿这种高频时序数据,到底该怎么存。

3.1 存储方案三剑客:HDF5、Parquet、SQLite

这三样东西,我都在生产环境里用过。各有各的脾气,咱们一个一个说。

3.4.1 HDF5:科学计算的老大哥

HDF5,全称Hierarchical Data Format。说白了,就是一种能塞下海量数据的文件格式。我最早接触它是在做气象数据分析的时候,后来发现拿来做订单簿存储,简直绝配。

优点:

  • 速度快:读取大块连续数据时,HDF5几乎是碾压级别的。我测试过,读取100万条订单簿快照,HDF5比CSV快了将近20倍。
  • 支持压缩:默认的gzip压缩,能把数据体积压到原来的1/5左右。磁盘空间省了,IO压力也小了。
  • 层次结构:你可以把数据组织成类似文件系统的结构。比如 /orderbook/btc_usdt/2024/01/15,这样查询起来非常直观。

缺点:

  • 并发写入差:HDF5在单线程写入时表现很好,但多线程同时写同一个文件,很容易出问题。我曾经在实盘回测时踩过这个坑,两个进程同时写,结果文件直接损坏了。
  • 生态相对封闭:虽然Python有h5py和pytables,但其他语言的支持就没那么好了。如果你团队里有人用Java或C++,可能会有点头疼。

我的建议:如果你做的是单机回测,数据量在几十GB以内,HDF5是性价比最高的选择。尤其是需要频繁读取全量数据做分析时,它的优势很明显。

3.4.2 Parquet:大数据生态的宠儿

Parquet是Hadoop生态里出来的格式。我一开始觉得它太重了,直到有一次需要处理TB级别的订单簿数据,才发现它的好。

优点:

  • 列式存储:订单簿数据有很多字段,但很多时候你只需要其中几列。比如我只想看买卖价差,Parquet可以只读取那两列,IO开销小得惊人。
  • 压缩率极高:同样的数据,Parquet用snappy压缩后,体积只有HDF5的一半左右。我存过一年的BTC订单簿数据,HDF5用了200GB,Parquet只用了110GB。
  • 生态好:Spark、Pandas、DuckDB都原生支持Parquet。跨平台、跨语言,基本没有障碍。

缺点:

  • 小文件性能差:Parquet是为大文件设计的。如果你把数据切成很多小文件(比如每个文件只有几MB),读写效率会急剧下降。我见过有人把每秒的订单簿快照存成单独的文件,结果查询时慢到怀疑人生。
  • 写入开销大:每次写入Parquet,都需要先缓存一批数据,然后一次性刷盘。不适合做实时写入。

避坑指南:我曾经把Parquet文件切得太小,导致查询时频繁打开关闭文件句柄,系统直接卡死了。后来我改成每小时合并一次文件,问题就解决了。记住,Parquet文件最好在100MB以上。

3.4.3 SQLite:轻量级的关系数据库

SQLite,很多人觉得它就是个玩具。但说实话,在数据量不大(几GB以内)的场景下,它比很多大数据库都好用。

优点:

  • 零配置:不需要安装服务,不需要配置端口,一个文件搞定。我经常在开发环境里用它做原型验证。
  • 支持SQL:查询灵活,可以按时间范围、价格区间、买卖方向任意组合。比如「查询2024年1月15日14:00到14:05之间,卖一价大于50000的订单簿快照」,一条SQL就搞定了。
  • 事务支持:写入时保证原子性,不会出现数据损坏的问题。

缺点:

  • 写入性能瓶颈:SQLite是单线程写入的。如果你每秒要写入几千条订单簿快照,它会成为瓶颈。我试过,超过每秒500次写入,延迟就开始飙升了。
  • 不适合海量数据:当数据量超过10GB时,SQLite的查询性能会明显下降。索引维护的成本也越来越高。

注意:SQLite不适合做高频写入。如果你需要实时记录每一笔订单簿变化,建议用其他方案。但如果你只是做离线分析,SQLite是个不错的选择。

3.2 三种方案对比一览

我整理了一张表,方便你快速对比:

特性 HDF5 Parquet SQLite
读取速度(全量) ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐
读取速度(条件查询) ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
写入速度 ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐
压缩率 ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐
并发支持 ⭐⭐⭐ ⭐⭐
生态兼容性 ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
适用场景 单机大文件分析 大数据分布式处理 小规模灵活查询

3.3 时间序列数据库选型

如果你觉得文件格式不够用,想要一个真正的数据库来管理订单簿数据,那就得考虑时序数据库了。

我试过几个主流的,说说我的感受。

3.3.1 InfluxDB

InfluxDB,时序数据库里的老牌选手。我最早用它来存股票Tick数据。

  • 优点:写入速度极快,查询语法简单(类SQL),自带数据保留策略(自动删除旧数据)。
  • 缺点:集群版要收费,单机版数据量大了之后性能下降明显。我试过存了半年的数据后,查询延迟从毫秒级变成了秒级。

3.3.2 TimescaleDB

TimescaleDB,基于PostgreSQL的时序数据库。说白了,就是在关系数据库上加了时序优化。

  • 优点:完全兼容PostgreSQL,可以用所有PG的生态工具。支持复杂的JOIN查询,适合做订单簿和交易数据的关联分析。
  • 缺点:写入性能不如InfluxDB,尤其是在高并发场景下。我测试过,同样硬件条件下,TimescaleDB的写入吞吐量只有InfluxDB的60%左右。

3.3.3 ClickHouse

ClickHouse,列式存储的OLAP数据库。我最近两年一直在用,越来越喜欢。

  • 优点:查询速度极快,尤其是做聚合分析。比如计算每分钟的平均买卖价差,ClickHouse能在毫秒级返回结果。压缩率也很高,我存了一年的订单簿数据,原始数据大概5TB,ClickHouse只用了800GB。
  • 缺点:不适合单条数据的频繁更新。订单簿数据是追加写入的,所以这个问题不大。但如果你需要频繁修改历史数据,ClickHouse就不太合适了。

我的选择:目前我在生产环境用的是ClickHouse。原因很简单——查询快、压缩高、生态好。配合Grafana做可视化,效果非常棒。但如果你需要事务支持或者复杂的关联查询,TimescaleDB可能更合适。

3.4 核心逻辑:存储方案选型决策流程

说了这么多,到底该怎么选?我画了一张图,帮你理清思路:

订单簿数据存储方案选型决策流程 数据量有多大? 小于10GB → 大于10GB SQLite 或 HDF5 Parquet 或 时序DB 需要SQL查询? 是 → SQLite 否 → HDF5 需要实时写入? 是 → 时序DB 否 → Parquet 最终选择:根据实际场景灵活组合使用

嗯,这张图基本概括了我的选型思路。你想想看,如果你的数据量只有几个GB,用SQLite做灵活查询,配合HDF5做批量分析,完全够用了。但如果数据量上了百GB,甚至TB级别,那就老老实实用Parquet或者ClickHouse吧。

我个人习惯是:开发阶段用SQLite,快速验证想法;生产环境用ClickHouse,保证性能和稳定性。中间的数据转换,用Parquet作为中间格式,方便在不同系统之间流转。

好了,存储方案这块儿就聊到这儿。记住一点:没有最好的方案,只有最适合你场景的方案。多试试,多踩坑,慢慢就有感觉了。

专注资料整理