今天发布 Polars(Polars)2.0 版本。此前公告说明版本跃升缘由,本篇探讨 2.0 引入的功能。虽非刻意大型发布,仍含诸多亮点:初步启用 out-of-core(溢写磁盘)支持、核心性能提升、一流 SQL 支持使 Polars 在 TPC-H 与 TPC-DS 基准领先 DataFusion(DataFusion)和 DuckDB(DuckDB),新增 Map 类型及更严格 dtype 显式性。Polars 2.0 将 SQL 作一等公民,近月覆盖扩展并改进优化器。
正文
今天我们发布 Polars 2.0。之前的公告解释了版本号提升的理由,这里说说 2.0 带来的功能。虽没打算做重大功能发布,仍有很多值得兴奋的改动。
本次亮点:
- 初步的核外(溢写磁盘)支持已启用
- 大量核心性能改进
- 一等公民级 SQL 支持,加上性能提升,让 Polars 在 TPC-H 和 TPC-DS[1] 基准中领先 DataFusion 和 DuckDB
- 新的
Map数据类型 - 更严格的 dtype 与显式性,带来更快反馈和更快的 AI 迭代
性能与 SQL 作为一等公民
Polars 2.0 起将 SQL 当作一等公民。过去几个月 SQL 覆盖率大幅提升。我们多年打造了扎实引擎,现在要让它支持更多负载,包括 SQL。为此做了许多优化器和引擎改进,重点是连接重排序、更好的公共子计划消除、动态谓词/布隆过滤器。
为看典型 SQL 基准表现,我们用源自 TPC-H 和 TPC-DS[1] 的数据,在 c7a.4xlarge(16 vCPU、32GB)和 c7a.metal(192 vCPU、384GB)上,对比最新 DuckDB 1.5.6、DuckDB 2.0 alpha 和 DataFusion 54.0.0。每查询热态跑 5 次,独立进程,60 秒超时。引擎/基准间清文件缓存。取各查询 5 次最佳,比总时间和几何平均。
数据用 tpcgen-cli parquet 生成,行组大小与 Polars、DuckDB 默认相近。SQL 由 DuckDB 1.5.6 生成,存于 EBS。
Polars 和两版 DuckDB 跑完所有查询;DataFusion 在 TPC-DS q72 等超时或内存不足,这些查询从结果排除。
默认 Polars 在除一个外的所有基准中最快。扩展到 192 线程时有固定开销,拖慢小数据查询;限 32 核时全胜。原因已诊断,下版修。复现仓库已公开(github.com/pola-rs/polars-2.0-benchmark)。
流式引擎与 OOC 默认开启
2.0 最大影响变更之一:LazyFrame 的 collect 默认走流式引擎,多数查询内存和性能大升。因流式引擎默认不保某些操作(join、group_by、unpivot 等)行序,需顺序可设 maintain_order=True。
核外(溢写磁盘)默认开,RAM 约 80% 时溢写(可能需调参)。当前支持排序、窗口函数等溢写,默认磁盘额度 64GB。后续将支持 join 和 group-by。
这两改动让 Polars 在高内存负载下更稳健,尤其对普通用户。
新 Map 数据类型
Polars 现直接支持 Arrow MapType 为 Map dtype,类似 Python 字典映射键值。2.0 前被读为 List(Struct({"key":..., "value":...}))。
作为支持 dtype,map 有专门表达式,如按键查找、遍历值等。例如可建含 user、scores(Map 类型)、subject 的 DataFrame,scores 存如 {"math":90,"art":75} 等;然后对其做 map.get("math")、map.get(pl.col("subject"))、map.contains_key("art")、map.len()、map.keys()、map.values(),得到对应数学分、按科分、是否含 art、长度、键列表、值列表等结果。
更严格的 Polars
Polars 力求严格、快速失败。错误应尽早抛出,而非管线跑 20 分钟才报。数据不匹配的隐式行为应 opt-in,以免藏 bug。AI 开发兴起让此更值:Agent 可用 collect_schema() 早验查询结构,不物化数据就抓 schema 错,加速反馈。非所有错都能编译期抓,依赖数据的默认更严,避免静默异果。见前帖例。
结语
很高兴 Polars 2.0 发布。未来数月改进:更好 OOC、大 CPU 数扩展、Polars Cloud 做最快分布式引擎。已起步 GeoPolars。问题请提 issue,升级指南已出。
基准附录
总时间(秒)如下表,Polars 32 线程仅在 c7a.metal 跑。
| 机器 | 核/内存 | 规模 | 基准 | Polars | Polars(32线程) | DuckDB 1.5.6 | DuckDB 2.0(alpha) | DataFusion | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | c7a.4xlarge | 16/32GB | SF10 | TPC-H | 3.22 | – | 4.44 | 4.27 | 7.41 | | c7a.4xlarge | 16/32GB | SF10 | TPC-DS | 12.59 | – | 15.92 | 14.13 | 34.36 | | c7a.4xlarge | 16/32GB | SF100 | TPC-H | 34.63 | – | 50.17 | 42.12 | 78.04 | | c7a.4xlarge | 16/32GB | SF100 | TPC-DS | 85.83 | – | 112.70 | 98.59 | 198.48 | | c7a.metal | 192/384GB | SF10 | TPC-H | 3.10 | 1.97 | 2.46 | 3.12 | 7.10 | | c7a.metal | 192/384GB | SF10 | TPC-DS | 23.16 | 9.63 | 12.25 | 12.92 | 42.17 | | c7a.metal | 192/384GB | SF100 | TPC-H | 9.85 | 19.91 | 17.39 | 21.05 | 49.91 | | c7a.metal | 192/384GB | SF100 | TPC-DS | 42.33 | 54.84 | 63.48 | 68.66 | 202.95 |
几何平均查询时间(秒)如下:
| 机器 | 核/内存 | 规模 | 基准 | Polars | Polars(32线程) | DuckDB 1.5.6 | DuckDB 2.0(alpha) | DataFusion | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | c7a.4xlarge | 16/32GB | SF10 | TPC-H | 0.120 | – | 0.167 | 0.165 | 0.252 | | c7a.4xlarge | 16/32GB | SF10 | TPC-DS | 0.077 | – | 0.103 | 0.104 | 0.136 | | c7a.4xlarge | 16/32GB | SF100 | TPC-H | 1.206 | – | 1.698 | 1.593 | 2.505 | | c7a.4xlarge | 16/32GB | SF100 | TPC-DS | 0.411 | – | 0.676 | 0.642 | 1.032 | | c7a.metal | 192/384GB | SF10 | TPC-H | 0.121 | 0.076 | 0.096 | 0.122 | 0.273 | | c7a.metal | 192/384GB | SF10 | TPC-DS | 0.196 | 0.067 | 0.087 | 0.102 | 0.254 | | c7a.metal | 192/384GB | SF100 | TPC-H | 0.377 | 0.660 | 0.639 | 0.763 | 1.701 | | c7a.metal | 192/384GB | SF100 | TPC-DS | 0.306 | 0.261 | 0.415 | 0.491 | 1.272 |
SF100 从 16 到 192 vCPU,Polars TPC-H 快 3.8x、TPC-DS 2.2x(总和),优于 DuckDB 等;SF10 额外核对默认 Polars 无助。
评论
社区整体对 Polars 2.0 正式版发布持积极采用与期待态度,少数人则更关心它与 Pandas 等工具的生态边界以及旧版接口陷阱是否改善。
认为 Polars 已经过生产验证并期待 2.0 正式版
- 多名用户分享在量化交易、天气大数据预计算及团队分析栈中顺利使用 Polars 的经历,表达对稳定版发布的迫切心情(较多人) > 用候选版本预计算数十亿条天气数据堪称救星,今晚就能升正式版了(@therno)
认为 Polars 与 Pandas 及 DuckDB 等生态定位仍待澄清
- 部分用户疑惑 Polars 是否已成 Pandas 全面替代品,或它与 DuckDB、DataFusion 等相近项目是否应走向融合,反映出对工具选型的迷茫与整合预期(少数人) > 没紧跟潮流,想知道 Polars 有没有彻底取代 Pandas,各自还有没有更适合的场景(@gozzoo)
担心旧版 eager 与 lazy 执行模式混淆的陷阱未清除
- 有用户最在意过去循环中误用 collect() 摧毁查询计划这类易错设计在新版是否修正,说明底层接口心智负担仍是迁移顾虑(少数人) > 过去一半的 bug 都来自循环里随手 collect 把查询计划搞挂,希望新版清理了这类坑(@hnd9q09qk4)
有价值的补充
- Polars 支持直接使用 SQL 语法进行数据查询与处理,这一能力让部分刚了解的用户感到惊喜。