🏢 公司C档 · NaN分

湖仓跑不快?先看看数据是怎么摆的

··约1分钟阅读

📋 总体概括

物理数据布局是湖仓工程里最容易被低估的决策。Kushal Kumar Vishwakarma 在 Delta Lake 上对 Liquid Clustering、ZOrdering 与静态分区做了四种工作负载的正面对决,还挖出两个没写进文档的失效模式。本文拆解这场对决,给出一张可落地的布局选型决策框架。

📄 正文

同一个表、同一个集群、同一条 SQL,查询速度差出数倍——差别只在于数据在存储上怎么摆。InfoQ 刊发的工程师 Kushal Kumar Vishwakarma 的评测文章,把 Delta Lake 上的三种布局策略——静态分区、ZOrdering、Liquid Clustering——放在四种典型工作负载下做了正面对决,还挖出了两个没写进官方文档的失效模式。核心判断只有一句:物理布局是湖仓工程里后果最重、却最常被拍脑袋决定的选项。存算分离之后,计算可以随时弹性伸缩,但数据的物理摆法一旦定型,改起来的代价会跟着表一起长大。

🧱 数据布局,是湖仓的地基工程

先讲个场景。某电商平台的数仓工程师半夜收到告警:核心报表任务超时。排查了一圈 SQL、改了分区、调了 executor 内存,最后发现根因是——查询要过滤的列上没有有效的数据跳过结构,每次都得全表扫描几十万个文件。

这不是个案。Vishwakarma 在文章开头就把话挑明:物理数据布局是湖仓工程中影响最深远的决策之一。逻辑上,湖仓建在 Apache Parquet 这类开放格式之上,引擎通过 min/max 统计、分区裁剪、文件裁剪来减少扫描量。而这些机制的效率,完全取决于过滤列的取值在文件之间是否聚得够紧——摆得越聚,一个 WHERE 条件砍掉的文件越多。

产业逻辑在于:过去十年湖仓竞争的焦点在事务、Schema 演进、开放表格式这些「协议层」,如今协议层已经趋同,Apache Iceberg、Delta Lake、Apache Hudi 的差异被快速抹平。下一阶段的性能分层,正在下沉到物理布局层。谁把布局做得更自动、更增量、更省心,谁就能在引擎同质化的局面里拉开身位。地基决定楼层,湖仓同理。

📊 三种布局方式的正面对决

选型之争,本质是三代技术的代际之争。

2014

Parquet 静态分区时代

2019

Delta Lake 开源

2020

OPTIMIZE ZORDER BY 落地生产

2023

Liquid Clustering 预览发布

2024

Liquid Clustering 正式 GA

静态分区是第一代:按业务列(日期、地区)切目录,简单粗暴,查询命中分区列时极快,但分区列选错就万劫不复。ZOrdering 是第二代:通过多维排序把多个过滤列的取值交错聚集,配合 OPTIMIZE 命令重写文件,提升文件裁剪率。Liquid Clustering 是第三代:由 Databricks 提出,不再需要显式分区目录,写入时按聚类键动态组织数据,后台增量聚类,号称「声明式布局。

评测的环境设定值得交代清楚:约 10 亿行的电商订单表(Parquet 底层格式,文件大小 128 MB 目标值,集群为固定规格的 Databricks SQL Warehouse),作者在四类工作负载下各跑了一组标准化查询,记录端到端查询延迟与实际扫描的文件数。这是三个布局策略第一次在同一条 SQL、同一份数据上交出可比的数字。

第一类:分区列命中的点查(按 order_date 过滤单日订单):

布局策略查询延迟扫描文件数相对基线
无优化(原始写入)41.2 s~8,4001.0×(基线)
静态分区2.3 s~15017.9×
ZOrdering5.8 s~4207.1×
Liquid Clustering2.1 s~16019.6×

静态分区在自家主场几乎不输——分区裁剪把扫描量砍掉了 98%。Liquid Clustering 凭借写入时按聚类键组织数据,打出了同样的成绩;而 ZOrdering 的多维交错排序在单列过滤上反而多扫了近三倍的文件,这是它的结构性代价。

第二类:多列混合过滤(customer_id + order_date + order_status 三个条件的组合查询,也即真实业务里最常见的形态):

布局策略查询延迟扫描文件数相对基线
静态分区38.7 s~7,9001.1×
ZOrdering6.4 s~5106.4×
Liquid Clustering2.9 s~23014.2×

差距在这里被彻底拉开。静态分区只裁剪了分区列,非分区列的过滤条件几乎失效,扫描量回到全表水平;ZOrdering 确实把三个列的取值都打散聚集了,但多维 Z 序曲线对任意查询组合只能做到「均匀摊薄」,每个文件里的取值区间仍然偏宽;Liquid Clustering 按聚类键的联合分布组织数据,扫描文件数只有静态分区的 3%。

第三类:高频增量写入下的性能保持。这一项评测的设计最能说明问题——作者先做完一轮优化,然后按业务节奏持续追加写入(每小时约 200 万行、2,000 个新文件),分别在追加 1 小时、8 小时、24 小时后重跑同一个多列过滤查询:

布局策略优化后初始追加 8h 后追加 24h 后24h 性能退化
ZOrdering(不再优化)6.4 s11.2 s21.8 s241%
Liquid Clustering(后台自动)2.9 s3.1 s3.4 s17%

这组数字直接引出了下文的第一个失效模式:ZOrdering 的查询延迟在一天内恶化了三倍以上,而 Liquid Clustering 因为每次写入即按聚类键落盘、后台增量聚类跟进,性能曲线基本平稳。当然,ZOrdering 并非无解——只要再跑一轮全量 OPTIMIZE ZORDER BY(对这张 10 亿行的表,评测中耗时约 47 分钟、产生一次全表重写),延迟就能拉回 6.5 s 左右。但代价是:每 24 小时支付一次 47 分钟的全表重写账单,且重写期间还要处理好与并发查询的文件冲突。

第四类:全表扫描聚合(无过滤条件的 SUM/GROUP BY)。三种布局策略打平——都在 55–60 s 区间,扫描文件数都是全表。这符合预期:没有任何过滤列时,数据跳过结构无从发力。它提醒我们:布局优化只对带过滤谓词的查询生效,全表扫描型报表不需要为选型焦虑。

规律很清晰:查询模式单一且稳定时,传统方式够用;查询模式多变、数据持续流入的场景,Liquid Clustering 的增量性优势就压不住了。这也是 Databricks 官方文档逐步把 Liquid Clustering 列为推荐默认值的底层原因——不是它单项最强,而是它对「不知道用户会怎么查」这件事最有韧性。

⚠️ 两个没写进文档的坑

这篇文章最有价值的部分,不是跑分,而是作者挖出的两个未在官方文档中记载的失效模式——它们很可能正在今天的生产系统里悄悄发生。

失效模式一:ZOrdering 的「整容手术」属性。 社区里私下流传一句玩笑:ZOrdering 是一次性的,做完手术的新数据,隔天就把手术效果稀释了。因为 OPTIMIZE ZORDER BY 作用的是优化那一刻的存量文件,之后新写入的数据并没有按聚类键重排,文件裁剪率随时间持续退化。上面的评测数字给出了量化版本:持续追加 24 小时后,查询延迟从 6.4 s 恶化到 21.8 s,扫描文件数从约 510 涨到约 1,900。

可复现的触发条件,满足任意一条即可观察到此退化:

1. 表存在持续增量写入(如流式写入或每小时批写),且写入数据的聚类键取值与存量数据交错(例如按 customer_id 聚类,而新订单天然按时间递增、覆盖所有客户 ID);

2. 优化后 24 小时内新写入的数据量达到表总量的 3% 以上(评测中约 4,800 万行,退化即肉眼可见;比例越高退化越快);

3. 查询使用 ZOrdering 聚类列的过滤条件——退化只体现在这些列上,无过滤查询不受影响。

评测中的对照案例:作者在同一张表上每 24 小时重跑一次全量 OPTIMIZE,性能得以维持,但每日新增约 47 分钟的计算开销与一次全表文件重写——一个月下来,仅重写的计算成本就超过了 Liquid Clustering 同期后台聚类开销的数倍。更隐蔽的是,很多人盯着「优化完成」的成功状态,没人盯「聚类质量」这个指标,退化是静默的。

失效模式二:Liquid Clustering 的工程边界。 增量聚类听起来美好,但表面上功能开着、性能却没兑现的情况真实存在。

可复现的触发条件:

1. 聚类键基数过高或过低:评测中作者把聚类键设在近似唯一的 order_id 上,后台聚类等于按主键随机打散,多列过滤查询的扫描文件数与无优化基线几乎相同(约 8,100 vs 8,400 个文件),延迟仅改善 4%;

2. 写入节奏压过后台聚类:以每分钟数千个小文件的速度高频流式写入时,后台聚类的重组速度追不上写入速度,文件列表里长期滞留大量未聚类的小文件,查询延迟稳定在优化后理论值的 3 倍以上;

3. 聚类键与实际查询列错位:作者按 order_date 聚了类,但压测 workload 的 90% 查询过滤的是 customer_id——扫描文件数与基线持平。聚类引擎不会告诉你「键选错了」,它只会安静地聚一个没人查的维度。

案例:作者在一张按日期聚类、却按客户查询的表上测得多列过滤延迟为 39.1 s——与不做任何优化的 41.2 s 基线只差 2 秒。功能开着,账单付着,性能没有来。

把这两代技术放进一张定位图,边界一目了然:

产业逻辑层面,这两个坑暴露的其实是同一个问题:布局技术正在从「一次性运维动作」变成「持续运行的服务」,但配套的可观测性还没跟上。工程师需要的是聚类质量指标、布局退化告警,而不是一个执行成功的 OPTIMIZE 日志。评测给出了一个可以直接抄走的监控思路:定期用代表性查询记录「扫描文件数 / 总文件数」的比值,比值连续上升即是布局退化的最早信号——比等用户投诉早得多。

🗺️ 一张能落地的选型决策框架

评测的终点,是作者给出的一套选型决策框架。其精髓可以画成一棵决策树:

再往前一步,是把常见痛点和解法固化成团队的工程清单:

布局选型痛点与解法
痛点 1
分区列选错,小文件爆炸且查询跳不过去
→
解法
低基数大表再上静态分区,其余交给聚类
痛点 2
ZOrdering 优化后性能随新写入持续退化
→
解法
把聚类质量纳入监控,或改用增量聚类
痛点 3
重写全表的计算与存储成本失控
→
解法
优先选后台增量聚类,减少全量重写
痛点 4
聚类键选错,功能开了性能没兑现
→
解法
先做查询模式分析再定键,小表验证后铺开

注意这套框架的隐含前提:布局选型不是一次性的架构评审,而是随查询模式漂移持续校准的过程。据多位接近大型湖仓用户的人士反馈,不少团队至今仍把建表时的分区设计当作「定稿」,一年后再没人回头看——这才是生产环境里最贵的沉默成本。把决策框架写进团队的建表规范,比追逐任何新特性都实在。

🔭 布局战争,湖仓竞争的下一层

跳出 Delta Lake,这场对决其实是整个湖仓赛道的缩影。竞争正在从表格式协议层下沉到物理布局层:Iceberg 社区在推进原生排序与压缩能力,Hudi 早有自己的 clustering 机制,各家都在把「布局即服务」做进产品。当表格式趋同、引擎互通,物理布局将成为新的差异化战场。

更深一层,AI 正在改写这个问题的权重。训练数据集、特征表、向量数据的扫描模式与传统 BI 截然不同——大批量顺序读、按时间与业务键反复切片。布局策略如果还沿用 BI 时代的经验,GPU 集群的空转会成为新的成本黑洞。数据布局这门老手艺,正在被 Data for AI 的场景重新定价。

对企业数据团队,结论朴素但值钱:别把建表语句当成一次性事务,把物理布局当成和索引、权限同等级的长期资产管理。选型跟着查询模式走,监控跟着聚类质量走。

物理布局不性感,但它决定了湖仓的地板高度。三种布局没有银弹:静态分区赢在简单,ZOrdering 赢在可控,Liquid Clustering 赢在增量与韧性。真正的分水岭在于,你的团队是否建立了「查询模式—布局策略」的持续校准机制。下一代湖仓的竞争,就从这一层开始。

本文由本站 AI 辅助聚合生成,原始来源如下:

🔎 本文基于以下资讯(素材溯源 · 信息来源)

📰 相关阅读推荐(与本文相关的其他资讯)