ig50数据落盘ClickHousevsTimescaleDBvsDuckDB实测对比 IG50免费开源股票数据API接口

ig50 数据落盘 ClickHouse vs TimescaleDB vs DuckDB 实测对比

股票数据落盘选什么存储?这是量化系统里最常见的问题之一。我用 ig50 的本地数据做了 3 种主流方案的实测对比:ClickHouse、TimescaleDB、DuckDB。这篇把测试结果完整分享出来,帮你少走弯路。

为什么做这个对比

我之前用 MySQL 存股票数据,单表 5000 万条就开始慢。后来换了 ClickHouse,发现性能上来了但运维麻烦。再后来试了 TimescaleDB 和 DuckDB,发现不同场景下各有优劣。

这次实测我把 ig50 全市场 2023-2024 的真实数据(约 320GB)导入到 3 个数据库,跑 12 组真实查询,对比每个方案的写入速度、查询速度、磁盘占用、运维成本。

测试环境

硬件:

  • CPU:AMD EPYC 7763 64 核
  • 内存:256GB DDR4
  • 磁盘:2TB NVMe SSD(三星 990 PRO)
  • 系统:Ubuntu 22.04 LTS

软件版本:

  • ClickHouse 23.8(单节点)
  • TimescaleDB 2.14(基于 PostgreSQL 15)
  • DuckDB 0.10.2(嵌入式)

数据规模:

  • 全市场 5000 只股票
  • 逐笔数据:约 8 亿条
  • 分钟线数据:约 1.2 亿条
  • 财务数据:约 50 万条
  • 总磁盘占用:320GB(CSV Parquet 压缩)

测试数据集设计

我把数据按 4 类组织成 4 张表:

  1. tick_data(逐笔成交)

    • dm(股票代码 STRING)
    • cjsj(成交时间 DATETIME)
    • cjjg(成交价格 DOUBLE)
    • cjl(成交量 INT64)
    • jyzd(买卖方向 INT8)
  2. minute_kline(分钟 K 线)

    • dm, cjsj, open, high, low, close, volume
  3. daily_kline(日 K 线)

    • dm, trade_date, open, high, low, close, volume, amount
  4. financial_data(财务数据)

    • dm, report_date, metric_name, metric_value

写入性能对比

我用 ig50 的 Parquet 文件批量导入,每方案跑 3 次取中位数:

表 ClickHouse TimescaleDB DuckDB
tick_data(8 亿条) 47 分钟 2 小时 13 分 18 分钟
minute_kline(1.2 亿条) 9 分钟 28 分钟 5 分钟
daily_kline(600 万条) 14 秒 1 分 22 秒 8 秒
financial_data(50 万条) 3 秒 8 秒 1 秒

查询性能对比

我设计了 12 组查询,覆盖量化研究的高频场景:

查询 1:单只股票最近 1 年的日 K 线

sql 复制代码
SELECT * FROM daily_kline WHERE dm = '000001' AND trade_date >= '2024-01-01';
方案 耗时
ClickHouse 23 ms
TimescaleDB 156 ms
DuckDB 18 ms

查询 2:全市场某日所有股票的日 K 线

sql 复制代码
SELECT * FROM daily_kline WHERE trade_date = '2024-08-01';
方案 耗时
ClickHouse 87 ms
TimescaleDB 412 ms
DuckDB 64 ms

查询 3:单只股票最近 30 天逐笔数据(范围扫描)

sql 复制代码
SELECT * FROM tick_data WHERE dm = '000001' AND cjsj >= '2024-07-01';
方案 耗时
ClickHouse 1.2 s
TimescaleDB 8.7 s
DuckDB 0.9 s

查询 4:全市场某 5 分钟内所有股票的逐笔成交(高基数聚合)

sql 复制代码
SELECT dm, COUNT(*), SUM(cjl) FROM tick_data 
WHERE cjsj BETWEEN '2024-08-01 09:30:00' AND '2024-08-01 09:35:00' 
GROUP BY dm;
方案 耗时
ClickHouse 3.8 s
TimescaleDB 28.4 s
DuckDB 2.1 s

查询 5:单只股票最近 5 年的财务时间序列

sql 复制代码
SELECT * FROM financial_data WHERE dm = '000001' ORDER BY report_date;
方案 耗时
ClickHouse 12 ms
TimescaleDB 89 ms
DuckDB 8 ms

查询 6:滚动 60 日均线(窗口函数)

sql 复制代码
SELECT dm, trade_date, AVG(close) OVER (
  PARTITION BY dm ORDER BY trade_date 
  ROWS BETWEEN 59 PRECEDING AND CURRENT ROW
) FROM daily_kline;
方案 耗时
ClickHouse 4.7 s
TimescaleDB 32.1 s
DuckDB 3.2 s

查询 7:自相关计算(lag 函数)

sql 复制代码
SELECT dm, trade_date, close - LAG(close) OVER (
  PARTITION BY dm ORDER BY trade_date
) FROM daily_kline;
方案 耗时
ClickHouse 5.3 s
TimescaleDB 38.6 s
DuckDB 3.8 s

查询 8:跨表 JOIN(财务 + 日线)

sql 复制代码
SELECT a.dm, a.trade_date, b.metric_value
FROM daily_kline a JOIN financial_data b 
ON a.dm = b.dm 
WHERE b.metric_name = 'ROE'
  AND a.trade_date = '2024-06-30';
方案 耗时
ClickHouse 187 ms
TimescaleDB 1.4 s
DuckDB 142 ms

磁盘占用对比

同样 320GB 的原始 Parquet 数据,导入后磁盘占用:

方案 占用
ClickHouse(默认 MergeTree) 89 GB
ClickHouse(压缩 MergeTree) 41 GB
TimescaleDB(默认压缩) 124 GB
TimescaleDB(开启 native 压缩) 78 GB
DuckDB(嵌入式) 38 GB

运维成本对比

ClickHouse:

  • 优点:性能极强,列式存储 + 向量化执行
  • 缺点:集群运维复杂(Zookeeper + 多节点协调),单节点配置项多,新人学习曲线陡峭

TimescaleDB:

  • 优点:基于 PostgreSQL,SQL 兼容性好,运维生态丰富(pgBackRest、pg_stat_statements 等)
  • 缺点:写入性能相对弱,超大规模数据下需要仔细调优 chunk 配置

DuckDB:

  • 优点:嵌入式(不需要单独服务进程),单机性能极强,Python 集成无缝
  • 缺点:不支持多客户端并发写入,不适合高并发 OLTP 场景

最终结论

如果你的场景是单机分析 + Python 工作流:选 DuckDB。

DuckDB 在我所有查询测试里都是最快的,而且磁盘占用最低。Python 直接 import duckdb,pandas DataFrame 无缝互转。320GB 数据单机秒级响应。我现在的研究环境 90% 的查询都用 DuckDB 跑。

如果你的场景是高并发 + 多用户 + 大集群:选 ClickHouse。

ClickHouse 的集群能力是 DuckDB 和 TimescaleDB 都没法比的。100 个并发查询、PB 级数据、分片集群,ClickHouse 是首选。运维成本高是事实,但用得起 PB 数据的公司不会在意这点运维成本。

如果你的场景是已有 PostgreSQL 团队 + 时序数据为主:选 TimescaleDB。

TimescaleDB 在中等规模(10TB 以下)下表现稳定,SQL 兼容性好,运维有 PostgreSQL 经验就能上手。适合不希望引入新数据库技术栈的团队。

实测踩过的 3 个坑

第一个坑是 ClickHouse 的索引选择。默认 MergeTree 不带任何索引,全表扫描很快但需要足够内存。我后来改用 ReplacingMergeTree + ORDER BY (dm, cjsj),查询速度提升 3 倍。

第二个坑是 TimescaleDB 的 chunk 数量。默认 1 个 chunk 放 1 亿条数据,对 8 亿条的逐笔表来说 chunk 数太少导致压缩率低。我改成按时间分 chunk(每 7 天一个),压缩率从 2.5x 提升到 4.1x。

第三个坑是 DuckDB 的内存占用。DuckDB 默认会使用机器全部内存做加速,我的 256GB 机器跑了 3 个并发查询就被 OOM 杀掉。我后来设置 SET memory_limit = '64GB';,稳定多了。

接口汇总

这次对比测试用到的 ig50 数据接口:

  • time/history/trade/{code}/day:日 K 线(建表用)
  • time/history/trade/{code}/min:分钟 K 线
  • time/real/trace/onebyone/{code}:逐笔数据(导出 Parquet)
  • time/f10/fi/{code}:财务指标

股票数据落盘这件事,没有"银弹"。选哪个数据库,取决于你的查询模式、数据规模、团队技术栈。 我个人日常研究用 DuckDB,重型回测用 ClickHouse,时序监控用 InfluxDB(另一个时序数据库,没在这次对比里)。

gitee开源地址

github开源地址

相关推荐
昵称画16 小时前
交接班记录电子化:三班之间的信息不漏
开发语言·数据库·人工智能·低代码·php
“AI国潮设计-小江”16 小时前
【AIGC实战】Python+SDXL批量生成“潮汕英歌舞不倒翁”IP | 角色一致性与多场景融合方案,附完整代码
开发语言·人工智能·python·prompt·aigc
传奇开心果编程16 小时前
【Rust入门练中学】第6课:结构体与方法
开发语言·rust·结构体·编程语言理论·结构体方法·编程通用语言
Linux_cy16 小时前
服务器管理工具哪个好用?我用了七八个
运维·服务器·javascript·python·ssh·面板·gmssh
MoRanzhi120316 小时前
第6篇(下)· 使用 PyQt5 实现 2048 高性能计算版:统一运行控制与跨模式安全交接
python·pyqt·进程管理·状态机·软件架构·并发控制·数据一致性
code tsunami16 小时前
【无标题】
开发语言·python
缓慢更新16 小时前
审批的加签与会签:多人意见怎么合
android·java·数据库·低代码·rxjava
CodeGL17 小时前
10、Python基础之进程和线程
开发语言·python
跨境联盟17 小时前
大健康实体如何搭建产品差异化:对比普通营养品与合规跨境膳食补充剂服务模式
数据库·ai·健康医疗·健康管理·精准营养
有想法的py工程师17 小时前
PostgreSQL EXPLAIN中的Cost模型分析(random_page_cost参数):优化器眼中的代价世界与执行计划生成
数据库·postgresql