首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Parquet格式火了!量化分析师用DuckDB和Polars读取,TB级数据秒处理

Parquet格式火了!量化分析师用DuckDB和Polars读取,TB级数据秒处理

作者头像
不吃草的牛德
发布2026-04-23 13:09:44
发布2026-04-23 13:09:44
1670
举报
文章被收录于专栏:RustRust

Parquet格式火了!量化分析师用DuckDB和Polars读取,TB级数据秒处理,CSV时代彻底拜拜!

你们还在为TB级tick数据、因子库、回测数据集头秃吗?

每天打开终端:

  • • Pandas读个CSV,电脑直接风扇狂转、内存OOM、卡成PPT;
  • • 加载一天全市场数据就要等20分钟,回测一次喝完两杯咖啡;
  • • 云服务器账单每月多出几百块,就因为IO和内存爆炸?

醒醒吧!2026年了,还在用行式CSV?Parquet格式 + DuckDB/Polars组合拳,直接把数据处理速度干到10倍以上,内存占用直降80%

今天这篇爆款干货,我把Parquet在量化分析里的核心玩法扒得干干净净,还手把手教你DuckDB和Polars两种读取姿势新增重磅:Parquet分区优化技巧(实测能再提速3-10倍!),最后给出真实场景硬核对比,帮你选出最香方案!

点赞+收藏,读完直接上手,效率起飞!🚀

一、Parquet到底有多香?量化人为什么集体转投?

Parquet是Apache基金会的列式存储格式,专为大数据分析而生,和CSV(行式)完全不是一个维度。

核心优势(量化场景直击痛点):

  1. 1. 极致压缩:Snappy/Zstd/Gzip,同一份tick数据,CSV 100GB → Parquet只要10-20GB,节省80%+存储!
  2. 2. 列式读取:只需要的列(比如只读closevolume)直接拉取,不用全表扫,IO狂降。
  3. 3. 谓词下推+统计元数据:min/max、bloom filter自动跳过无关分区,过滤“600519 2024-01-01”这种查询,秒出结果。
  4. 4. 原生分区支持:按date/symbol分区,Hive风格目录结构,查询特定股票特定日期像查数据库一样快。
  5. 5. Schema自带:类型严格,时间戳、浮点精度永不乱,量化回测再也不怕隐形bug。

量化人真实使用场景

  • • 历史行情库(日线/分钟线/tick)
  • • 多因子Alpha库
  • • 订单簿/逐笔成交数据
  • • 替代HDF5/Feather,跨语言(Python/Rust/Spark)无缝互通

一句话:Parquet不是工具,是量化数据基础设施的降维打击

二、Parquet分区优化技巧

分区是Parquet在量化时间序列数据上的杀手级特性。正确分区能让引擎直接跳过无关文件和row group,大幅减少IO和扫描量。错误分区反而会制造“小文件问题”,导致元数据爆炸、查询变慢。

量化场景最优分区策略(A股/美股/期货通用):

  1. 1. 核心原则
    • 按高频过滤列分区:优先选查询中最常用的过滤字段,且基数(distinct值)不要太高
    • 避免过分区:每个分区文件大小控制在128MB~1GB最佳(太小→小文件问题;太大→无法有效跳过)。
    • 时间序列优先:量化数据天然按时间有序,按date/year/month分区最香。
  2. 2. 推荐分区组合(从好到更好)
    • 基础:仅按date=YYYY-MM-DD分区(适合日级回测)。
    • 进阶year=YYYY/month=MM/day=DD(Hive风格,便于按月/季过滤)。
    • 量化最强date=YYYY-MM-DD/symbol=600519 或先按date再按symbol子分区(单日全市场数据或单股历史数据查询极快)。
    • 混合:按symbol粗分区 + 文件内按timestamp排序(充分利用row group统计信息)。

写入分区Parquet实战代码(Polars最灵活):

代码语言:javascript
复制
import polars as pl

# 假设df已有 date 和 symbol 列
df.write_parquet(
    "data/quant_db/",
    compression="zstd",           # 压缩率最高,量化数据推荐
    partition_by=["date", "symbol"],  # Hive风格:data/date=2024-01-01/symbol=600519/xxx.parquet
    row_group_size=128_000,       # 行组大小,平衡压缩与谓词下推(DuckDB默认约122k)
    statistics=True               # 必须开启!让min/max统计生效,加速过滤
)

DuckDB写入分区

代码语言:javascript
复制
COPY (SELECT * FROM df) 
TO 'data/quant_db/' 
(FORMAT parquet, PARTITION_BY (date, symbol), COMPRESSION 'zstd');

读取优化(自动利用分区):

  • • Polars:pl.scan_parquet("data/quant_db/date=2024-01-01/*/*.parquet") 或直接scan_parquet("data/quant_db/") + filter,引擎自动pruning。
  • • DuckDB:SELECT * FROM 'data/quant_db/**'read_parquet('data/quant_db/date=2024-*/symbol=6005*/*.parquet')

额外提速技巧

  • 数据排序:写入前按timestampsymbol排序,提升row group统计准确性。
  • Row Group大小:太小浪费压缩,太大过滤不精准;128k~256k行是甜点。
  • 避免小文件:合并小分区,或用PER_THREAD_OUTPUT加速写入。
  • S3/云存储:分区后查询只拉取相关文件,成本直降。
  • 实测效果:140GB数据集分区后,DuckDB内存降8倍,Polars降4倍;单日查询从分钟级→秒级。

避坑:不要按高基数列(如每笔timestamp、order_id)分区;不要产生成千上万小文件(<50MB)。

三、实战1:DuckDB读取Parquet —— SQL党最爱,复杂分析无敌

DuckDB是嵌入式OLAP神器,零配置、向量量化执行,直接把Parquet当数据库查,不用全加载到内存。分区后谓词下推更猛!

安装(一行搞定)

代码语言:javascript
复制
pip install duckdb polars pyarrow

代码示例(超级实用,带分区)

代码语言:javascript
复制
import duckdb

query = """
SELECT 
    symbol,
    timestamp,
    open,
    high,
    low,
    close,
    volume
FROM 'data/quant_db/**' 
WHERE date = '2024-01-01' 
  AND symbol = '600519' 
  AND volume > 1000000
ORDER BY timestamp DESC
LIMIT 1000
"""

df = duckdb.sql(query).df()
print(df.head())

四、实战2:Polars读取Parquet —— Python党最爱,DataFrame操作飞起

Polars是Rust底层下一代DataFrame,懒加载+查询优化,配合分区如虎添翼。

代码示例(Lazy模式 + 分区)

代码语言:javascript
复制
import polars as pl

lf = pl.scan_parquet("data/quant_db/date=2024-01-01/*/*.parquet")  # 精确到分区目录,超快

result = (
    lf
    .filter(pl.col("volume") > 1_000_000)
    .select(["symbol", "timestamp", "close", "volume"])
    .sort("timestamp")
    .head(1000)
    .collect(streaming=True)   # 大数据推荐
)
print(result)

五、DuckDB vs Polars 场景硬核对比(量化人必看!)

场景维度

DuckDB(SQL党)

Polars(DataFrame党)

量化推荐场景

数据规模

10GB~TB级,超内存也能跑

1GB~100GB+,懒加载极致

>100GB选DuckDB;<50GB Polars更快

查询类型

复杂SQL、JOIN、多表聚合无敌

表达式API、特征工程、Pipeline超爽

回测多因子JOIN → DuckDB特征衍生 → Polars

性能(实测反馈)

SQL优化器强,聚合/窗口函数更快

Rust单线程/多线程经常更快

Polars单机DataFrame胜;DuckDB分析查询胜

内存占用

极低,可落盘;分区后降8倍

极低,懒执行;分区后降4倍

两者都吊打Pandas

分区利用

自动Hive pruning极强

scan_parquet + glob支持优秀

两者均优秀,混合用最强

学习成本

SQL老手0成本

Python DataFrame老手0成本

已会SQL选DuckDB;已会Pandas选Polars

最强玩法

DuckDB读取+Polars加工

-

DuckDB ETL → Polars特征工程

总结一句话

  • 想写SQL、复杂分析、超大分区查询DuckDB闭眼入
  • 想纯Python流式Pipeline、特征工程、ML前处理Polars闭眼入
  • 分区后最强DuckDB读取+Polars加工duckdb.sql(...).pl() 一行搞定)

六、量化落地最佳实践(直接抄作业)

  1. 1. 写入Parquet:用pl.write_parquet(..., compression="zstd", partition_by=["date", "symbol"], statistics=True)
  2. 2. S3/对象存储:两者都原生支持,零修改
  3. 3. 混合流水线:DuckDB做ETL清洗 → Polars做因子计算 → Arrow内存零拷贝
  4. 4. 监控:用pl.show_graph() 或 DuckDB EXPLAIN 看优化计划 + 分区pruning效果
  5. 5. 分区调优:先小规模测试不同分区方案,观察查询时间和内存

写在最后

Parquet + 正确分区,不是一个格式,是量化效率的降维武器。用上DuckDB和Polars,你会发现以前的“数据等待”时间全部变成了“策略迭代”时间。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2026-04-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Rust火箭工坊 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、Parquet到底有多香?量化人为什么集体转投?
  • 二、Parquet分区优化技巧
  • 三、实战1:DuckDB读取Parquet —— SQL党最爱,复杂分析无敌
  • 四、实战2:Polars读取Parquet —— Python党最爱,DataFrame操作飞起
  • 五、DuckDB vs Polars 场景硬核对比(量化人必看!)
  • 六、量化落地最佳实践(直接抄作业)
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档