过去两年,数据处理圈流行一句话:"用 pandas 写,换 Polars 跑,快了 10 倍"。Polars 用 Rust 重写了数据框引擎的底层,多线程、向量化、惰性求值一样不缺,官方演示过在笔记本上流式处理约 250 GB 的数据集。Star 数约 39.9k,速度在新一代引擎里坐稳头把交椅。
Polars 官方定位:用 Rust 编写的 Dataframe 分析查询引擎,目标是快、易用且富有表达力。本文第 1 节讲项目概况,第 2 节剖析快的技术原因,第 3 节用官方示例上手,第 4 节深入表达式与生态,第 5 节给迁移建议,最后总结。
1、项目概述
Polars 采用 MIT 协议,商业嵌入零顾虑。安装只要一行:
pip install polars
它不挑平台:Python、Rust、Node.js、R 都有绑定,还内置 SQL 接口。数据格式全面拥抱 Apache Arrow,与 pandas、Spark、DuckDB 近零拷贝互通。
特性清单里最值得记的四条:
- Rust 实现,多线程并行加 SIMD 向量化
- 惰性与即时两种执行模式,带查询优化器
- 超出内存的数据集可用流式引擎处理
- 表达式 API 富有表达力,可插件扩展
2、快的三个来源
Polars 的性能来自三层叠加。第一层是并行执行:Rust 无 GIL,所有核都能吃满,同样的 groupby 聚合,pandas 单核跑 8 秒的活,Polars 在 8 核机器上常在 1 秒出头。第二层是列式内存布局加 SIMD:数据按列紧凑存放,缓存命中率高,向量化指令一次处理多条数据。第三层是惰性执行——用 scan_csv、scan_parquet 声明数据源,链式写完过滤、聚合、排序,最后调用 collect() 时,查询优化器先审视整棵表达式树,做谓词下推、列削减、操作合并,然后才生成执行计划。这个模型对习惯 SQL 的人非常自然。
3、快速上手
README 里的官方示例完整展示了惰性 API 的典型链路,逐字摘录如下:
import polars as pl
q = (
pl.scan_parquet("data.parquet")
.filter(pl.col("category") == "electronics")
.group_by("merchant")
.agg(
pl.col("amount").sum().alias("total_amount"),
pl.len().alias("number_of_transactions"),
)
.sort("total_amount", descending=True)
)
df = q.collect()
从上往下读:scan_parquet 声明数据源(scan 是惰性模式,read 是即时模式);filter 用 pl.col("category") 引用列;agg 同时算两列聚合,alias 命名输出列。直到 collect() 才真正执行,此时优化器介入。
如果数据集大过内存,把最后一行换成 q.collect(engine="streaming"),同样的查询走流式引擎分批处理——代码不变,规模上了一个数量级。
4、表达式与生态扩展
表达式 API 是 Polars 的灵魂。pl.col("amount").sum() 里的 .sum() 不是立即计算,而是返回一个待执行的表达式对象,可以继续组合:嵌套窗口、条件分支 pl.when(...).then(...).otherwise(...)、在同一个 select 里对同一列派生多个输出。表达式发生在查询计划里,优化器看得见全貌,这是它比逐行调用型 API 快的根本原因。
工程上还有几个值得知道的点:
| 能力 | 说明 |
|---|---|
| 表达式插件 | 用 Rust 写自定义表达式并注册 |
| I/O 插件 | 自定义数据源接入扫描层 |
| GPU 加速 | NVIDIA GPU 为可选启用项 |
| Polars Cloud | 分布式集群扩展 |
版本兼容有一个细节:不支持 AVX2 指令集的老 CPU 上需要设置 LTS_CPU=1 安装长期支持构建。性能对标可参考 官方文档 附带的 PDS-H 基准集。
5、对比 pandas 与迁移建议
把两个引擎放在决策清单里看:十 GB 以内的探索分析,pandas 生态更熟、答案更多;重复执行的批处理管道,Polars 的多核优势持续兑现;数据超过内存,流式引擎最省事;团队 SQL 背景浓,表达式语义也更接近 SQL。
迁移成本比想象中低:pd.read_parquet 换 pl.scan_parquet,groupby() 换 group_by(),df["col"] 换 pl.col("col")。思维转变只有一个——从"立即改数据"转为"声明变换再 collect"。另一个忠告:不要逐行迭代,.iter_rows() 等于放弃全部并行优势。
6、总结
Polars 证明了数据框引擎可以既快又好用:Rust 多线程内核、Arrow 内存格式、带优化器的惰性执行、超内存流式处理,四件套对 pandas 单线程模型构成降维打击。对于新建的数据管道和性能敏感的批处理任务,建议默认选 Polars、用 scan_parquet 加 collect 的惰性写法起步;对于存量 pandas 代码和重交互的探索场景,建议保留 pandas 做前端、通过 Arrow 互通,按瓶颈逐步迁移——两个引擎共存是当下最务实的架构。

