数据库湖仓与存储技术评论分析· 4148 字· 约7分钟阅读

一个默认值改动,悄悄击穿数据管道

A
AI编辑团队AI 原创内容
2026-10-14 17:26 发布· 本文由作者与AI协作完成
本内容由人工智能生成,仅供研究参考,不构成投资建议。
💡

Polars 2.0 把 collect() 默认切到流式引擎,join 行序不再保证;同期 Doris 5.0 缝合流湖、ClickHouse 在性价比上拉开 1996 倍差距。三件事指向同一趋势:执行引擎集体用确定性换速度,正确性正从引擎责任变成用户责任。

2026年10月6日,Polars 2.0 发布,一行 collect() 的默认行为被悄悄改写。几乎同一时间窗口,Apache Doris 5.0 公布了流湖统一查询方案,ClickHouse Cloud 则在一项基准测试里甩开了 Redshift Serverless。三件事看似不相干,其实指向同一个判断:执行引擎正在集体用『确定性』换『速度和成本』,而账单,最终由下游的每一条数据管道来付。

🔄 一行 collect(),埋了多少雷

很多团队升级完框架,跑一遍冒烟测试就上线。真正的雷,埋在没人显式断言的地方。

Polars 作者 Ritchie Vink 在发布说明里只用了 一句话交代这次变更:LazyFrame.collect() 现在默认运行流式引擎。带来的潜在影响是,对 join、group_by 和 unpivot 这三类操作,除非你显式设置 maintain_order,引擎不再保证输出保持输入行序。如果你的代码在逐行比对输出,或者写出一个文件、由下游按行位读取,那么同一份代码在不同机器上可能给出不同答案。

这不是理论推演。在实际验证中,Polars 2.0.0 对 200 万行数据做 inner join,默认配置下输出行序已经乱了;给 join 加上 maintain_order 后,输入顺序才得以保留。也就是说,一行参数决定对错。

产业逻辑其实很清楚:过去十年,DataFrame 和 SQL 引擎之间形成过一种『隐形契约』——join 大体保持左表顺序、group_by 大体按 key 排列。没有任何文档承诺过这一点,但大量管道靠它活着。流式引擎要并行、要分区、要 out-of-core,就必须拆掉这个契约。问题在于,Polars 拆契约的方式是『改默认值』,而不是『换显式开关』——前者省了所有老用户的思考,后者才配得上破坏性变更。一位在金融行业做数仓的朋友私下说得更直白:『排序保证这种东西,一直是引擎在替用户还债,现在债主上门了。』

顺带一提,本次升级还默认打开了 out-of-core 处理:内存用到约 80% 就开始向磁盘溢写,磁盘预算默认 64GB。性能上更抗打,但故障面也变宽了——磁盘 IO 抖动现在会直接反映到查询延迟里。发布说明里的基准测试也留了脚注:那是厂商自己的运行结果,与官方 TPC 结果不可比。这句脚注,值得每个做技术选型的人抄在工位上。

🌊 流与湖的缝合线

OLAP 世界的另一头,Apache Doris 5.0 在做一件更苦的活:把流和湖缝在同一张查询界面后面。

方案分两块。对 Fluss,5.0 可以直接读取它的 log 表和 primary-key 表;对湖侧,则把 Paimon 的历史数据与流上的最新数据合并,在一次查询里同时看到『昨天的全量』和『此刻的增量』。这就是所谓的 Union Read。

听起来只是又一个『湖仓一体』故事?差别在实现难度。素材里特意点名了一个细节:Union Read 过程中的 JVM 内存管理。把流表的低延迟更新和湖列存的大规模扫描拼进同一个执行计划,内存水位完全不可预测——流侧是持续写入的日志,湖侧是随时可能放大的扫描,两者挤在同一个 JVM 里,管理不好就是 OOM。这不是 API 层面的缝合,是执行器层面的缝合。

产业逻辑在于:过去『流归 Flink,批归 Spark,查询归 ClickHouse』的分工正在被打通诉求侵蚀。用户不想维护三条链路、三份一致性语义。谁能把『一条查询横跨流和湖』做到工程可靠,谁就拿到下一轮实时分析的入场券——而可靠性恰恰取决于 Polars 那个问题:执行引擎敢不敢、以及如何重排你的数据。流湖缝合和行序破坏,本质是同一枚硬币的两面:并行与合并换性能,代价是确定性。

💰 1996 倍差距从哪来

如果说前两件事关乎正确性,第三件事就直接关乎账单了。

CostBench 基准给出了一个足够刺眼的数字:在『新鲜数据进得来、快速答案出得去』这条实时分析链路上,ClickHouse Cloud 对 Redshift Serverless 的单位成本性能(performance per dollar)领先了 1,996 倍。是的,四位数。

差距不是单一环节造成的,而是从数据落地到查询返回的整条链路叠加:数据摄取的 freshness、列存引擎对扫描的裁剪能力、查询并发的资源隔离,再到 Serverless 定价模型本身的『弹性税』——为不固定的负载模式付出的溢价。专用引擎(purpose-built)在单一场景里压榨硬件的极限,通用云仓则为通用性付费,这中间的效率差被倍数放大。

事件关键变更被打破的默认工程对策
Polars 2.0collect() 默认走流式引擎join/group_by/unpivot 行序显式 maintain_order
Apache Doris 5.0读 Fluss 流表 + Paimon 湖数据流批分链路的查询习惯Union Read 内存治理
ClickHouse CloudCostBench 性价比领先一体化云仓的定价惯性按真实负载自建基准

当然要泼一盆冷水:1996 倍来自基准测试,正如 Polars 发布脚注所言——厂商主导的基准与官方 TPC 结果不可比。CostBench 的负载若恰好命中列存引擎的甜区,倍数会被放大;换成宽表点查或高并发混合负载,结论可能温和得多。业界私下流传的一句话是:『所有倍数先除以十,再看剩下的还能不能打动你。』

但方向性判断不受倍数影响:分析引擎的竞争焦点,已经从『功能有没有』彻底转向『执行经济学』——同样一份数据、同样一个查询,你比对手便宜几个数量级。Serverless 不等于省钱,专用引擎不等于狭隘,2026 年的选型逻辑要重写了。

⚠️ 正确性成了用户的责任

把三件事放在一起,能看到一幅完整的图景。

流式引擎时代的工程对策
痛点 1
升级后行序悄悄变化
→
解法
关键 join 与 group_by 显式设置 maintain_order
痛点 2
内存充足才跑得动的旧假设失效
→
解法
接受 out-of-core 溢写并实测磁盘预算
痛点 3
厂商基准倍数无法复现
→
解法
用自有数据和真实负载自建基准
痛点 4
流批两套查询链路成本高
→
解法
评估 Doris Union Read 式统一查询

引擎的演进方向是确定的:更多并行、更多溢写、更多跨源合并,速度和单位成本还有巨大下探空间。这意味着『输出顺序与输入一致』『内存够就能跑』『基准数字可复制』这些旧默认,会被一个接一个地拆除。而拆除的方式往往不是发公告,而是发新版本。

据多位接近开源社区的人士观察,这类『默认值变更』引发的故障报告,在未来一两年会集中爆发——因为大量管道的行序依赖,连写代码的人自己都不知道。给数据团队的建议只有四条,全都不性感:锁版本、灰度升级;对进入下游落盘的关键 join 显式声明 maintain_order;测试用例里加行序断言,而不是只比对行数;任何引擎选型,用自己最刁钻的那份真实数据重跑一遍基准。

时间线拉出来看更直观:

  • 2026-10-06:Polars 2.0 发布,collect() 默认启用流式引擎,join/group_by/unpivot 不再保证输入行序
  • 同期:Apache Doris 5.0 公布与 Fluss 的流湖统一读取,直指 JVM 内存治理
  • 同期:CostBench 公布 ClickHouse Cloud 对 Redshift Serverless 1,996× 的单位成本性能结果

结语

2026 年的这一波引擎升级,本质是一场契约重签:引擎把性能、成本、流湖统一的红线往前推了一大步,同时把正确性的举证责任推回给用户。这不是引擎的堕落,而是工程成熟的必经阶段——只是很多人还没意识到自己签的是新合同。下一个被拆除的『隐形默认』会是什么?大概率不在发布说明的第一段,而在脚注里。养成读脚注的习惯,比追任何新框架都值钱。