数据分布在几十台机器上,不代表计算就真的分布了。过去,Polars Cloud 遇到需要查看整列的表达式,仍可能把所有分区汇到一个阶段,交给单个 worker 处理。0.9.0 开始补上这块短板,同时改进对象存储读取和 Iceberg 写入。它值得关注,因为这些能力直接决定 Polars 能否把单机上的查询体验延伸到云端集群。
本文信息均来自 Polars 官方发布博客,尚无独立信源交叉验证;其中性能数字是官方在特定配置下的自测结果。
表达式不再总挤到一台机器
这次的主角是 expression lowering——把用户写的高层表达式转换成执行引擎可运行的底层算子。Polars Cloud 此前已经能分布式执行 join、group_by 和 select 等操作,但表达式本身并未完全跟上。
例如,查询要筛出热量等于全列最大值的记录。max 必须查看整列。此前各分区的数据会经过 shuffle——按计算需要重新分发数据——汇入单一阶段,再由一个 worker 完成。这既削弱并行度,也容易让单节点成为瓶颈。
0.9.0 在 select、with_columns 和 filter 中启用了表达式下沉,让部分表达式采用分布式算法执行。官方预计,当 first、max、mean、sum、var、std 或 unique 等聚合表达式与其他表达式组合时,改善最明显。
但这不是“所有表达式全面分布式”。尚无分布式实现的表达式仍会回退到原来的 single-stage 行为。好处是旧查询可以继续运行;代价是实际加速幅度取决于查询里用了什么表达式。
云端瓶颈不只在计算
对象存储通过对象键读写数据,不像本地块设备那样工作。请求延迟、并发数和分段传输都会影响吞吐。Polars 1.42 引入的 adaptive concurrency controller 会根据观测到的带宽和延迟,动态调整同时在途的请求数;0.9.0 把它部署到了 Polars Cloud 集群端,现有查询升级集群后即可受益,无需修改 API。
Polars 官方称,在 TPC-H scale factor 1000、32 台 m6i.xlarge 实例的 I/O-bound 测试中,总运行时间下降 17%,部分查询耗时减半。这只能说明该特定配置下的结果,不能直接外推为所有工作负载的整体性能提升。
从读取到落表,链路更完整了
0.9.0 还加入 distributed Iceberg sink。Apache Iceberg 是用元数据管理文件、快照和表结构演进的开放表格式;sink 则负责把计算结果按其事务和元数据规则写成表。新版本允许 worker 并行写入 Parquet 数据文件,最后以单一步骤提交表事务,支持 append 和 overwrite。该功能要求集群安装 pyiceberg,目前仍标记为 unstable。
Python 自定义数据源也向前走了一步。引擎无法自行切分不透明的 Python source,但现在能把多个 Python scan 的 union 识别为一个 multi-scan source。用户可先手动划分数据源,再让 scheduler 把不同分支分发给各个 worker。
此外,本地部署集群支持手动增减 worker,规划器会按当前 worker 数调整分区;Observatory 增加了 disk I/O metrics。这些更新不像表达式下沉那样醒目,却补齐了集群运维与诊断环节。
为什么值得关注
0.9.0 的意义不在某个单项跑分,而在执行链路同时变厚:查询计划中的更多表达式可以分布式运行,云端读取能自适应并发,结果还能直接写入 Iceberg。Polars Cloud 正从“把 Polars 放到集群上跑”,进一步靠近覆盖读取、计算、写入和运维的数据平台。
局限与未知
- 官方尚未公布 TPC-H 的逐查询结果、基线版本、重复次数与方差,17% 和“部分查询减半”仍需等待详细拆解。
- 分布式表达式覆盖范围没有完整清单,未实现部分仍会落回单 worker。
ClusterContext存在破坏性变更:compute_address改为uri,旧参数与scheduler_port未经弃用期便被删除,升级后旧代码会抛出TypeError;原始材料末尾截断,完整迁移说明可能还有缺失。