俯视两条平行铁轨与挡土墙,钢轨笔直伸向画面深处

这次升级最容易被忽略,但影响最大的一条

10 月 6 日,Polars 2.0 正式发布,作者 Ritchie Vink。三个要点里,真正会改变日常的是这一条:对 LazyFrame 调 collect,现在默认走流式引擎。多数查询的内存占用和执行时间都因此明显下降。之所以必须跳大版本号,是因为流式引擎在 join、group_by、unpivot 这类操作上不再保证行序——如果你的流程依赖行序,得显式打开 maintain_order=True。与此同时,溢写磁盘(out-of-core)默认开启,内存用到约 80% 就开始落盘,默认磁盘预算是 64GB,目前支持排序、窗口函数和大量表达式,join 与 group_by 还在路上。

SQL 从附加功能变成一等公民

2.0 是 Polars 正式把 SQL 当一等公民的分界点。为此他们重做了优化器:连接重排序、更好的公共子计划消除、动态谓词与 bloom 过滤器。效果用 TPC-H 和 TPC-DS 的对标来呈现,同场的对手是 DuckDB 1.5.6、DuckDB 2.0 alpha(版本号 2.0.0.dev2610011535)和 DataFusion 54.0.0。

把数字摊开看,比结论更有用

测试机两台:c7a.4xlarge(16 vCPU / 32GB)和 c7a.metal(192 vCPU / 384GB)。每条查询在热态下跑 5 次,每次独立进程、60 秒超时,取最好成绩。16 vCPU 上,SF10 的 TPC-H 总耗时:Polars 3.22 秒,DuckDB 1.5.6 是 4.44 秒,DuckDB 2.0 alpha 4.27 秒,DataFusion 7.41 秒;SF100 的 TPC-H:34.63 对 50.17 / 42.12 / 78.04 秒。DataFusion 在 TPC-DS q72 上超时(q67 也超时过一次),在 16 vCPU 机器上跑 TPC-H q18 时内存不足。另一处很诚实的自曝是:Polars 扩到 192 线程时有固定开销,小数据查询反而吃亏;限制在 32 核时,它在所有基准里都是并列最快或直接最快。作者说已定位原因,争取下个版本修掉。

另外两件顺手做掉的事

一是新增 Arrow MapType 作为原生 Map 类型,可以像 Python 字典一样用 map.get、contains_key、keys、values,键还能来自另一列;以前这种数据只能读成 List(Struct)。二是更严格:能在编译查询计划阶段报的错就别拖到跑 20 分钟才炸,智能体可以先调 collect_schema() 校验结构与类型,不落地数据就拿到反馈——官方把这一点直接和「AI 驱动的开发迭代速度」挂了钩。

对做企业数字化、小团队的实际启发

三条。第一,默认开流式和溢写,等于把「内存不够就跑不动」这个常见翻车点降低了,中小团队用单机处理几千万行数据变得更可行,不必先上分布式集群。第二,升级到 2.0 前一定要过一遍迁移指南,重点查有没有依赖行序的 join、group_by——这类 bug 不会报错,只会静默换顺序,最后体现成报表数字对不上。第三,别只看「谁更快」的结论:同一份数据、同一台机器、32 线程对 192 线程的结果可以反过来,选型必须用自己的真实数据量去测。Polars 官方也把复现仓库放出来了,这比任何宣传语都有说服力。