处理一张很大的表,就像搬一屋子的书。旧办法可能先把书全部堆进客厅,再分类、筛选和装箱;流式办法则是一批批送进来,边处理边送走。后者通常不必同时占用那么大的空间。
Polars 2.0 最重要的变化正是如此:所有 LazyFrame 查询的默认执行路径,将从旧的内存引擎切换到 streaming engine——流式执行引擎。这里的“流式”不代表数据必须来自实时行情或传感器,而是计算时把数据分批推进,尽量避免把全部中间结果一起塞进内存。
不过,“全面接管”需要加一道边界:它说的是 LazyFrame 的默认引擎,不是 Polars 的所有执行场景。根据 Ritchie Vink 发布的 Polars 官方博客,目前公开的是 2.0 首个 release candidate(RC,正式发布前的候选版本);正式版当时预计在随后几周到来。下文的性能和兼容性判断也都来自这一官方单一信源,尚无独立基准交叉验证。
大版本,重点却不是加功能
Polars 是处理表格数据的 DataFrame 工具。分析人员可以用它筛选、连接和汇总数据,而执行引擎负责把这些操作真正组织成计算。
LazyFrame 指惰性查询:用户先写下一串操作,直到调用 collect() 获取结果时才统一执行。这样,引擎就能先做查询优化——在结果不变的前提下重新安排步骤,例如提前过滤不需要的行,减少后续工作量。
官方说,2.0 并不追求一次塞进许多大功能。它更像一次清理工程:移除阻碍后续发展的旧设计,再把默认设置改成对多数人更合适的选择。版本号之所以升到 2.0,主要不是功能变多,而是部分默认行为和结果的可观察特征可能变化。
最大的默认变化是:engine="auto" 今后会解析为 streaming engine。多数用户不改代码,调用 collect() 时就会走新路径。官方预计,多数 LazyFrame 查询的内存占用和性能会明显改善,并称聚合操作可轻松达到约 5 倍提速。这个数字是官方预期,不是独立测试证明的“所有查询都快 5 倍”。
省下内存,也可能打乱队伍
流式执行的收益来自“分批处理”。如果查询能够让一批数据依次穿过筛选、连接和聚合步骤,引擎就不必长期保留所有中间结果。数据越大,这种内存规划的差别越重要。
代价则藏在行顺序里。官方明确提醒,join(按键连接两张表)、group_by(按类别分组)和 unpivot(把宽表转换成长表)等操作,默认不再保证用户能观察到的行序。计算结果的内容可能仍然正确,但输出排列未必与旧引擎一致。
这不是纯粹的显示问题。有些代码虽然没有明说,却暗中依赖原来的排列顺序。升级后,测试快照、逐行对比或下游处理都可能出现变化。需要固定顺序时,用户应显式设置 maintain_order。如果暂时不想迁移,也可以用 pl.Config.set_engine_affinity("in-memory") 在整个进程中保留旧引擎,或在单次查询里调用 collect(engine="in-memory")。
换句话说,2.0 把更省资源的路径设成默认,同时要求真正依赖行序的人把意图写清楚。
更严格,是为了更早暴露错误
另一条主线是“尽早失败”。Polars 希望数据不匹配时立即报错,而不是让流水线运行很久后才出问题,或悄悄产出看似正常的结果。
官方给出的例子很直观。一个整数用户 ID 超过 后,若被隐式转换为 Float64,可能无法保持精确值。旧行为会把不同类型转换到共同类型,两个原本相差 1 的 ID 可能因此被误判为相同。2.0 会直接报错,要求用户明确处理这种有损转换。
横向拼接也更严格。过去,两张行数不同的表横向合并时,缺少的位置可能被静默填成 null。2.0 默认抛出 ShapeError;如果用户确实需要补齐,必须明确选择 horizontal_extend。字符串转日期、整数与分类类型之间的转换,也改为使用含义更清楚的专用方法,而不是依赖模糊的 cast。
Polars 还提供 collect_schema():它可以在不真正生成整份结果的情况下解析字段类型,提前发现 schema——也就是表格字段名称与类型结构——层面的不匹配。官方特别把它放在 AI 编程场景下讨论:代理可以先检查查询结构,得到更快的反馈,再继续修改。不过,有些错误取决于实际数据,无法只靠查询计划提前发现。
为什么值得关注
这次变化影响的不只是一个开关。默认引擎决定查询怎样分批推进、需要保留多少中间数据,也会影响优化策略和迁移成本。对普通用户,它可能意味着无需重写查询就能减少内存压力;对维护生产任务的人,则意味着升级前必须检查行序依赖、类型转换和拼接行为。
这条路线也并非凭空出现。据 SuperDataScience Podcast,streaming engine 曾经历一次不太成功的早期尝试。Vink 表示,旧流式引擎很快“撞了墙”:传统研究多围绕 SQL、关系代数和逐行处理,而 Polars 的列式 DataFrame API 允许用户随时触及整列甚至全部数据,不天然适合流式执行。团队后来没有继续修补旧方案,而是按 Polars 自身语义重写。如今把它设为所有 LazyFrame 查询的默认路径,正是那次重写走向主舞台的结果。
局限与未知
- 当前材料对应首个 RC,不能写成 Polars 2.0 正式版已经发布;正式发布时间仍以官方后续发布为准。
- “约 5 倍”是官方对聚合操作的预期,缺少独立基准,也不能外推为所有工作负载的统一收益。
- 官方原文末尾被截断。更严格错误处理的完整范围及全部报错改进无法据此核实;迁移时应以官方完整迁移指南为准。