AutoComp:面向数据湖日志结构表的自动化数据压缩

53 阅读31分钟

摘要(Abstract)

数据湖中小文件激增会带来一系列挑战:查询性能下降、存储成本上升,以及分布式存储系统的可扩展性瓶颈。Delta Lake、Apache Iceberg 与 Apache Hudi 等日志结构表格式(LST)由于采用仅追加(append-only)的写入模式并伴随大量元数据操作,进一步加剧了这一问题。尽管压实(compaction) ——即将小文件合并为更少但更大的文件——是常见的治理手段,现有自动化机制在面对多样化负载与系统需求时,往往难以在收益与成本之间实现灵活而可扩展的权衡。本文提出 AutoComp:一个面向现代数据湖、可扩展的自动数据压实框架。基于在 LinkedIn 的部署经验,我们分析了小文件激增带来的运维影响,给出有效自动压实所需的关键要求,并展示 AutoComp 如何应对这些挑战。我们在合成基准与生产环境中进行评估,并通过与 OpenHouse(一个用于目录管理、模式治理与数据服务的控制平面)的集成,验证了文件数减少与查询性能的显著提升。我们认为,AutoComp 的内置可扩展性为压实系统的演进提供了坚实基础,便于未来集成更精细的多目标优化策略、按工作负载感知的压实方案,以及更广泛的数据布局优化支持。

1. 引言(Introduction)

近年,企业在数据管理上的策略发生显著转变,正逐步转向以数据湖为中心的架构。数据湖最初是将大量非结构化、未清洗或未治理的数据,存放在可扩展的分布式文件系统(如 HDFS)中的一种低成本选择,以替代昂贵的专有数据管理/文件系统。随着数据湖存储成本的下降,组织也开始用它来管理核心、受治理、结构化的数据。促成这一转变的,是广泛采用的可扩展存储服务(Amazon, 2025b;Microsoft, 2025b;Google Cloud, 2025a;Apache Ozone, 2025)以及高效的开源数据格式(Apache Parquet, 2025;Apache ORC, 2025),它们共同构成了跨多种工作负载的数据持久化基石。存放在分布式存储中的数据可以被各种引擎与应用访问,带来多重优势:(i)存储与计算解耦伸缩,提升效率并节约成本;(ii)消除数据孤岛,简化跨系统的复杂数据流转;(iii)按应用选择最优引擎,降低供应商锁定风险。多家商业平台已拥抱这一思路(Databricks, 2025b;Microsoft, 2025f;Snowflake, 2023)。

访问这些分布式存储系统的引擎与应用,往往需要在涉及读写的复杂事务中获得一致性与隔离性等保证。然而,这些存储系统主要为可扩展性与耐久性而设计,缺乏满足上述需求的并发与恢复能力。因此,出现了 Delta Lake(Delta Lake, 2025a;Armbrust 等, 2020)、Apache Iceberg(Apache Iceberg, 2025a)与 Apache Hudi(Apache Hudi, 2025a)等开放表格式——本文统称为日志结构表(LST) ——它们让结构化数据能够存放在数据湖存储上,同时保持对外部查询引擎的良好组织与优化,获得出色的查询性能。

从本质上看,这些 LST 基于开源列式格式(Apache Parquet, 2025;Apache ORC, 2025)将数据以不可变文件持久化,并提供:(i)一个记录表版本与属性(如模式与统计信息)的元数据层;(ii)一个在读写操作中协调与表交互的协议。在此过程中,目录服务(catalog)发挥关键作用:维护表元数据的引用,使各系统能够无缝访问与更新(LinkedIn, 2025;Apache Polaris(孵化中), 2025;Unity Catalog, 2025)。每次写入都会向表中追加新数据文件并更新相应元数据;随着时间推移,特别是在涓滴式写入写入端未调优的场景下,表内会逐步堆积大量小尺寸文件

小文件挑战(The Challenge of Small Files) 。小文件大量积累在以数据湖为中心的架构中引发严重问题,影响所有计算引擎与 LST 实现,这在既有研究与经验中已有广泛记录(Camacho-Rodríguez 等, 2024;Powers, 2023a;Goswami 与 Sarkar, 2023;Merced, 2022)。小文件会增加受管对象数量I/O 请求频次,从而给数据湖底层的分布式存储系统带来压力,影响其性能与扩展性(Ramakrishnan 等, 2017;Shvachko 等, 2021)。例如,在 HDFS 中,负责维护文件系统元数据的 NameNode 能管理的对象总量有限;当文件计数增长时,被管理对象数按比例上升,迫使 NameNode 承压并常常需要**联邦(federation)**来分摊负载。与此同时,小文件导致的高频 RPC 流量也会加重 HDFS 负担,从而需要更多 observer NameNode(只读副本)来有效应对读流量。

当每个小文件仅存少量行时,也会削弱列式格式的编码与压缩优势,从而降低数据访问与存储效率。此外,小文件会导致 LST 的元数据膨胀:每次事务都会把文件引用追加到日志或清单(manifest)中,使元数据规模增长,进而增加查询规划与维护操作所需时间,降低整体性能与效率。问题还可能带来金钱成本:云服务商通常根据 I/O 请求与数据传输量计费(Amazon, 2025a;Microsoft, 2025c;Google Cloud, 2025b)。

压实作为解法(Compaction as a Solution) 。当前最普遍的存储修复机制压实(compaction) :按目标文件大小重写表内数据文件,将众多小文件合并为更少的大文件,从而改善存储效率、查询性能(规划与执行两方面)与整体数据布局。不同 LST 都实现了各自的压实机制(Delta Lake, 2025b;Apache Iceberg, 2025b;Apache Hudi, 2025b)。业界实践各不相同(Microsoft, 2025g;Databricks, 2025a;Goswami 与 Sarkar, 2023;Syam, 2023):有的在写入后被动触发压实,有的用独立作业周期性优化存储布局;部分引擎集成了前摄(proactive)机制以维持近似最优布局,但这类优化往往各自为政,只满足某个引擎自身需求,而未兼顾可能访问同一份数据的其他引擎。

本文贡献(Contributions) 。针对 LST 中小文件激增的问题,我们结合一线实践提出一种自动化数据压实方案,主要贡献包括:

  • 产业场景下的小文件分析:以 LinkedIn 的真实场景为例,梳理由大量小文件造成的数据碎片化在运维上的挑战;总结小文件激增的常见成因,并展示其对存储效率与查询性能的影响(§2)。
  • 需求定义与 AutoComp 框架:基于上述发现,提出在实际环境中治理 LST 小文件所需的功能性与非功能性要求;据此设计 AutoComp 框架以满足这些要求,实现自动化、可扩展的数据压实(§3–§5)。
  • 系统化评估:在云环境下用合成基准评测 AutoComp 的效果;并报告其在 LinkedIn 上线后的影响,生产环境中小于 128MB 的文件数最高减少 44% ,同时改善查询性能(§6–§7)。
  • 未来方向:指出仍待改进的方面,并提出后续研究方向,以进一步完善 AutoComp 与 LST 压实技术(§8)。

2. 动机场景(Motivating Scenario)

在 LinkedIn,来自数千个服务的原始事件数据通过由 Apache Gobblin 驱动、集中管理的管道被摄入数据湖(Li 等,2021)。组织按多条业务线进行划分,每条业务线负责维护数据管道,用于产出派生数据、业务指标以及特征集。业务线工程师(下文为区别于数据基础设施工程师,统称为“终端用户”)主要使用 Apache Spark、Trino 与 Apache Flink 等计算引擎来开发这些管道。

image.png

LinkedIn 已采用 Apache Iceberg 作为这些管道生成数据的日志结构表(LST)格式,从而在其分析与人工智能工作负载中统一了数据存储实践。基于对 Iceberg 的采用,LinkedIn 还开发并开源了 OpenHouse(LinkedIn,2025),这是一个控制平面:为表定义、模式管理与元数据维护提供声明式编目,并通过数据服务对齐观测态与期望态。过去一年多来,LinkedIn 持续将存量与新增表纳入 OpenHouse 管理。如图 1 所示,相比由中心管道摄入的原始数据,终端用户作业生成的派生数据在文件大小分布上存在显著差异。中心管道遵循明确的写入模式:每 5 分钟将来自 Kafka 的原始事件写入 HDFS,并增量压实与去重按小时分区中,最终形成约 512 MB 的文件(即我们的目标文件大小)。由 24 个小时分段组成的日分区用于长期保存,而较小的检查点文件会在 3 天后过期。相比之下,终端用户基于 Spark、Trino 与 Flink 的作业既未以最优文件大小为目标设计,也未进行相应调优,因此会产生大量小文件。指望终端用户优先处理文件优化并不现实,因为他们的首要精力在于解决业务问题,而非低层的数据存储细节。

小文件产生的原因。这些派生表中小文件的激增,既与 Iceberg 的版本语义相关,也与终端用户作业的设计与配置有关:
(i) 插入(Inserts) :批量插入有机会生成接近最优大小的文件,但
引擎配置、并行度与内存约束
会显著影响最终文件数量。增量插入(包括 CDC 场景,Blue,2023)常会快速生成大量小文件。
(ii) 更新与删除(Updates/Deletes) :在 CoW(写时复制) 配置下,删除操作会影响数据在文件间的分布,导致文件大小不均MoR(读时合并) 配置则会产生增量(delta)文件并随时间累积。
(iii) 迁移(Migration) :当将既有 Parquet/ORC 数据迁入 Iceberg 时,通常会保留原有文件结构,仅在其上叠加 Iceberg 元数据(Apache Iceberg,2025e),从而形成次优的文件布局。
(iv) 元数据(Metadata) :为管理表状态,Iceberg 会为每张表引入额外元数据(如 manifestmanifest list)。这些新增元数据本身也会助长小文件数量的增长。

image.png

image.png

压实的影响(Impact of Compaction)
在用户派生数据中观察到的小文件尺寸分布模式,促使数据基础设施工程师首次在 LinkedIn 借助 OpenHouse 引入集中管理的压实(compaction) 。在最初的实现里,工程师会手动为特定表触发压实——这些表反复出现问题,例如查询失败、配额(quota)超限,以及 HDFS 命名空间(namespace)持续膨胀。实践证明这种做法是有效的:如图 2 所示,手动压实使文件大小分布回归目标区间,降低了存储系统负载并提升整体效率。

除了对存储层的正面影响外,我们也注意到文件激增会影响查询性能。不过,在生产环境中直接量化压实对查询性能的影响并不容易,因为基础设施工程师无法控制各业务线运行的具体工作负载。为此,我们使用 TPC-DS 基准(Nambiar and Poess, 2006)在规模因子 1000下进行了一组合成实验。结果如图 3:我们在一个 16 节点的 Spark 集群上,记录“单用户阶段(single-user phase)”的端到端运行时(该阶段包含全部 TPC-DS 查询),分别比较数据维护阶段前后。数据维护阶段中,约 3% 的数据通过删除与插入发生修改,从而在表中新增了数据文件。随后一次单用户阶段的性能明显劣化,执行时间增加到原来的 1.53×。然而,在手动触发压实后,性能恢复到与该工作负载初次执行相当的水平。该实验说明:有效的数据维护不仅对存储层必要,对查询执行的稳健性与效率也至关重要。需要注意的一个副作用是:当压实与用户工作负载并发运行时,可能产生写写冲突,导致重试与资源浪费,从而拉长执行时间。但我们在 §6 的实验中表明,收益通常大于成本

人工干预的局限(Limitations of Manual Intervention)
尽管压实本身行之有效,但手动挑选表来执行压实无法扩展以满足 LinkedIn 的运营需求。具体来说,为解决小文件问题,数据基础设施工程师投入了越来越多的时间来设计具成本效益的数据重组策略,同时还要保障可扩展性并维护/纳管更多表。这样的被动反应式方式难以为继:它往往等到用户工作流出故障后才能补救。与此同时,若要在 OpenHouse 中对全部已纳管的 2.1 万张表(预计明年增长到 10 万定期执行压实,其资本性支出(capex)与运营支出(opex)都会高得不可接受。我们的分析量化了问题规模:仅在受管摄取管道中,对约 3000原始事件表执行压实,日均计算消耗约 150 TB·小时(TBhrs)日峰值可达 600 TB·小时。因此,我们开始研发 AutoComp,以一种更节省资源的方式在 LinkedIn 启用压实,最初只在有限的一组表上执行。正如图 2 所示,即便在较短时间内,它也能显著见效:自上线以来,OpenHouse 得以更快地将文件大小分布推向目标尺寸(§7 将进一步讨论)。相比之下,按固定表集合预设频率运行压实,对文件大小分布的改善并不显著——尤其当系统进入准稳态后,可继续优化的空间变少。后续压实往往处理的已是尺寸良好且均衡的文件,边际收益很小。该收益递减现象凸显了静态压实计划的低效:它不能随数据模式与表使用的动态变化而自适应,因此迫切需要自动表选择自适应压实能力。

3. AutoComp 概览(AutoComp Overview)

基于前述场景得出的结论,我们的目标是在生产环境中设计与实现一个自动数据压实框架谨慎平衡其收益与成本。我们的设计由一组**功能性(FR)非功能性(NFR)**需求所引导,下面分别概述,随后给出 AutoComp 的方案。

3.1 功能性需求(Functional Requirements)

FR1:细粒度工作单元(Fine-grained work units)。
AutoComp 应基于动态数据分析自动选择压实对象,并识别最优粒度的工作单元执行压实,以最大化潜在收益。通过将压实工作负载拆分为更小的子表级(sub-table)工作单元独立处理,框架可以在来自不同大型表的分段之间有效分摊任务,提升并行度与资源利用,并优先处理最具影响力的分段。更小的工作单元也更易调度、资源需求更低,尤其适用于资源受限环境;它还能保证增量推进,并在发生失败或冲突时避免整表重启、提升容错性、减少对正在运行业务的干扰。但也需要意识到:更多任务实例会带来更高的启动开销

FR2:多种压实策略(Support for multiple compaction strategies)。
框架应支持多样化的压实策略,可按优化目标编码收益、成本或两者的权衡。例如,为降低存储层压力,可使用基于收益的触发器,贪心地优先处理小文件更多的表;在资源受限时,可叠加成本感知,优先那些低成本高收益的操作。通过在不同触发策略间切换,系统能适配多种场景,并在性能与资源使用之间维持平衡。

FR3:周期性与写后触发(Periodic and post-write execution triggers)。
框架应同时支持周期性触发大规模写入后的即时触发周期性执行可持续优化数据布局、防止长期碎片化并提供可预测的成本;而写后执行可对重大摄取后的数据立即重组,抑制小文件蔓延并改进后续性能。

3.2 非功能性需求(Non-Functional Requirements)

NFR1:可扩展性(Extensibility)。
框架需为未来扩展而设计,便于集成更多压实策略并适配新型工作负载。考虑到数据湖工作负载的多样性,能够在组件层面自由组合(如压实策略、调度策略)能让系统演进而无需大改造

NFR2:可解释性(Explainability)。
在相同输入条件(如文件大小分布、工作负载特征)下,框架应产出一致的决策确定性的决策有利于调试、测试、基准评测与行为文档化,使大规模生产环境中的优化器更透明、可管理

NFR3:跨平台兼容(Cross-platform compatibility)。
框架应能在不同的 LST 与目录实现无缝工作。这将其能力从 LinkedIn 的用例扩展到其他以数据湖为中心的平台(例如 Fabric(Microsoft, 2025f) )。这种灵活性让框架可适配更广泛的部署环境,扩大影响与适用范围

image.png

3.3 AutoComp:一个用于压实的通用框架

综合前文提出的期望与约束,我们在此给出一个面向 LST 的通用自动化压实框架(下文称 AutoComp)的工作流设计。我们采用“OODA(Observe–Orient–Decide–Act,观察—研判—决策—行动)”决策模型来映射框架内的压实流程。类似的思想也被 Netflix 的 auto-optimize 功能用于其特定场景(Syam, 2023)。我们的工作在相同理念之上进行了泛化与模块化:将压实决策工作流的各组件解耦,使 AutoComp 的使用者可以按自身需求自由定制。

如图 4 所示,OODA 的四个阶段各自关联输入、输出以及将输入转换为输出的动作。我们首先生成压实候选,在 observe(观察) 阶段针对这些候选提取下游决策所需的相关统计信息;这些统计既可以是文件级指标,也可以是表/分区级的候选特定统计。对候选的细粒度生成直接支持 FR1:确保压实任务能够在子表粒度执行,从而更高效地管理资源。

observe 阶段的输出进入 orient(研判) 阶段,在该阶段我们将前述统计转换为一组 traits(特征) 。这些特征用于描述候选的当前状态或其潜在收益/成本,例如“文件熵(file entropy)”或“重写数据文件的估算计算成本”。利用特征,AutoComp 可以以统一的方式表达不同的决策策略,从而在 decide(决策) 阶段依据不同目标对候选进行排序(满足 FR2)。此时会产生一份有序的压实清单,并在 act(行动) 阶段按序执行。

observe → orientorient → decide 之间可选用过滤器以进一步收敛候选集合。例如:根据表大小过滤过小的表;检查候选在近期是否发生频繁写入以避免压实期间的潜在冲突。AutoComp 还支持从 act 阶段回到 observe 阶段的反馈回路:例如回填新的分区文件数量或布局变化,用于持续改进后续压实决策。

AutoComp 的架构支持多种运行模式:既可以按固定计划独立运行,也可以在特定事件触发下前摄执行(符合 FR3)。这种灵活性使框架无需大幅改造即可适配不同的运维需求。另一方面,阶段化、模块化的设计满足 NFR1(可扩展性) :只要各阶段之间的数据交换结构保持一致,就能无缝加入新的压实策略或决策准则。此外,如果在各阶段选择确定性算法,AutoComp 便可满足 NFR2(可解释性) ,使决策行为透明、可预测。最后,AutoComp 可以通过连接器对接不同的 catalogLST,并依据统一的数据模型向系统提供输入,这满足 NFR3(跨平台兼容) ,提升了复用性与适用范围。

基于 AutoComp 的工作流,我们在 §4 详细给出构建该压实框架所需的关键实现细节,并在 §5 讨论触发压实的执行策略。


4. AutoComp 的实现细节

本节依次介绍:如何识别可压实的对象(候选生成,§4.1)、如何将系统统计有效地转化为可用的特征(§4.2)、如何基于目标进行候选的排序(§4.3),以及如何对已选候选进行调度(§4.4)。

4.1 候选的生成与过滤

下文中,我们将一个候选(candidate)定义为一组待被压实的文件集合。候选可以代表整张表,也可以按需将范围调整为分区(partition)快照(snapshot) ——这种调整既可手动配置,也可自动推断。比如,对于大表,将候选限定在分区级可以并行处理多个压实任务;将范围限定到快照级,则有助于对“相对新鲜的数据”进行更频繁的优化,从而保证该数据子集的性能目标。候选可以在工作流中以单一范围范围组合的方式生成。对单一范围触发工作流可以简化下游的调度(无需处理范围重叠),但相较于考虑完整候选空间,这种做法的灵活性较弱——不同表的布局可能需要不同的范围策略才能收益最大化。

候选生成后,工作流会结合统计与当前表的使用模式在多个阶段应用过滤机制以收敛候选集。关键挑战是:理解这些候选所在的表是如何被使用的,并据此应用恰当的过滤。例如,需要考虑表删除、表覆盖,或“中间表”的创建,以避免冗余或冲突的操作。这些过滤步骤与平台特性执行引擎密切相关。以 OpenHouse 为例:若某张表在预设时间窗口内刚创建,我们会跳过压实,以避免把计算预算花在不会影响系统长期健康的对象上。

同样,在 observe 阶段如何提取统计也依赖于平台特性。为将此步骤模块化,我们提出一套标准化的统计布局,同时容纳通用自定义指标。通用统计的例子包括:候选中的文件数及其文件大小;自定义统计则可包含候选的访问模式使用度量等——这类信息在并非所有系统中都可获得。

4.2 特征(Trait)的生成

orient(研判)阶段将 observe(观察) 阶段收集的统计转化为用于优先级与排序特征(traits) 。AutoComp 中的特征相互独立定义,排序时可以部分组合使用。我们的工作主要关注两大类特征:描述压实收益的特征(如文件数减少文件熵(Syam, 2023)),以及描述压实成本的特征(如计算成本)。二者结合可以进行成本—收益分析,据此筛选最有效的压实候选。

文件数减少(File Count Reduction)。 对于给定的压实候选 cc,我们将压实后的文件数减少量记为 ΔFc\Delta F_c,其估计方式为: 文件数减少(File Count Reduction)
对于给定的压实候选 (c),压实后的文件数减少量 (\Delta F_c) 估计为:

ΔFc=i=1FileCountc1!(FileSizei,c<TargetFileSizec)\Delta F_c =\sum_{i=1}^{\mathrm{FileCount}*c} \mathbf{1}!\left(\mathrm{FileSize}* {i,c}<\mathrm{TargetFileSize}_c\right)

其中,目标文件大小是一个可配置参数,可根据系统部署来选择。例如在 HDFS 场景下,常将其设置为与 HDFS 块大小一致;也可受工作负载特征影响。关于这些参数的调优,详见 §6.3。

计算成本(Compute Cost)
压实本身会产生计算成本,在生产环境尤需纳入考量,尤其当我们关注收益/成本比时。例如,若两个候选各自带来不同的文件数减少(如 200 vs. 100),且计算成本相近,则应优先选择前者;但若前者计算成本显著更高(比如因为文件更大),其收益/成本比可能不如后者。在资源受限场景下,压实任务必须受可用容量约束:计算成本超出预算的候选要么自动丢弃,要么在潜在收益足够大时标记为复核

对候选 cc 的压实计算资源需求(以 GB·小时计,记作 GBHrc\mathrm{GBHr}_c)可按下式估算:

GBHrc=ExecutorMemoryGB×(DataSizecRewriteBytesPerHour)\mathrm{GBHr}_c = \mathrm{ExecutorMemoryGB} \times \left( \frac{\mathrm{DataSize}_c}{\mathrm{RewriteBytesPerHour}} \right)

其中,ExecutorMemoryGB\mathrm{ExecutorMemoryGB} 是为压实任务分配给执行器的内存GBGBDataSizec\mathrm{DataSize}_c 是候选文件总字节数,RewriteBytesPerHour\mathrm{RewriteBytesPerHour} 是系统每小时可处理的字节吞吐(即重写速率)。该模型聚焦于执行器内存;其它要素(计算单元、磁盘与网络 I/O 等)留待后续工作。

4.3 候选排序与选择(Candidate Ranking and Selection)

目标:在 decide 阶段对压实候选进行排序并确定优先执行次序。我们考虑两类情形:资源不受限资源受限的压实系统。

资源不受限场景
在没有资源约束时,排序可简化为一个阈值型决策函数:当某些特征超出预设阈值即可(立即)触发压实。比如,为保持查询性能,系统可设定:当估计的文件数减少 (\Delta F_c) 至少达到 10% 时触发压实。此时,当表发生更新,observeorient 阶段会生成候选与其特征;若任一候选的 (\Delta F_c \ge 10%),则直接进入 act 阶段执行。该策略可前摄地压降文件数、提升用户侧体验,但也可能导致资源使用低效(尤其对临时或非关键表;可用自定义过滤器缓解),且频繁压实会推高成本,不一定适合所有生产环境。

资源受限场景
当资源必须严格管理时,我们建议基于多特征组合进行排序,在最大化文件数减少最小化计算成本之间权衡,并与可用容量对齐。形式化地,我们将候选排序建模为多目标优化问题(MOOP) ,并用加权求和将其标量化为单目标函数以便优先级比较。为保证一致性,先对各特征做 min–max 归一化

Ti,c=Ti,cmin!(Ti)max!(Ti)min!(Ti)[0,1] T'_{i,c} = \frac{T_{i,c}-\min!\left(T_i\right)} {\max!\left(T_i\right)-\min!\left(T_i\right)} \quad\in[0,1]

其中,Ti,cT_{i,c} 为候选 cc 的第 ii 个特征的原始值,Ti,cT'_{i,c} 为其归一化后数值。随后定义各目标的权重 wiw_i,使 wi=1\sum w_i=1。权重体现每个特征在 MOOP 中的相对重要性,可动态调整以反映当下优先级。

以“最大化文件数减少最小化计算成本”为例,候选 (c) 的标量化评分可写作:

Sc=w1×T1,cw2×T2,cS_c = w_1 \times T'_{1,c} - w_2 \times T'_{2,c}

其中 T1,cT' _{1,c} 为归一化后的文件数减少,T2,cT'_{2,c} 为归一化后的计算成本。按 ScS_c降序排列,得出总体更优的候选次序。

为确定可用计算预算,AutoComp 可基于集群特征计算(如 ExecutorMemoryGB\mathrm{ExecutorMemoryGB} 与预计完成所选候选所需时间),或由生产环境的固定预算(受 capex/组织限额约束)给出,以确保压实不超出上限。预算确定后,AutoComp 选择前 kk 个候选(kk 为预算允许的最大个数)。具体选择函数可因系统而异;一个实用的贪心启发式是:在预算内尽可能纳入高优先级的压实任务。

通过在排序阶段引入上述多目标权衡,AutoComp 能让压实决策同时面向性能资源效率最优化,并能随运行约束优先级变化进行动态自适应。

4.4. 压实调度(Compaction Scheduling)

自动压实流程的最后一步是在 act 阶段对已选中的压实候选进行调度。依据集群配置不同,压实既可以在同一集群上执行,也可以卸载到专用的压实集群,以尽量减少高写入量与资源占用对用户性能的影响。实践中,AutoComp 允许用户自定义调度器以适配特定集群需求。比如:当压实与用户事务运行在同一集群上时,可将压实任务顺序化以缓解资源争用;若使用模式可预测,也可将压实延迟到低峰时段执行。

此外,所选用的 LST 也会影响调度决策。以我们在 Apache Iceberg v1.2.0OpenHouse 上的实验为例,一个违反直觉的现象是:即使针对同一张表的不同分区并发执行压实,也可能产生冲突,导致压实失败。因此,任何调度算法都必须考虑所选 LST 的具体特性——不仅包括冲突解决机制,还包括压实过程中的**任务失败、恢复与检查点(checkpointing)**等行为(Apache Iceberg, 2025d),这些都会影响调度决策。

5. 自动化数据压实(Automatic Data Compaction)

在识别出需要压实的候选之后,下一步是确定何时触发压实。为了替代人工干预,我们希望依据集群健康度可用计算资源及其他相关指标,自动进行压实的调度与执行。自动压实可通过两种方式实现:
(i) 写后优化(Optimize-After-Write) :每当候选的文件发生修改时,评估其压实潜力;
(ii) 周期性压实(Periodic Compaction) :按照固定间隔(如每日一次)运行压实工作流,将压实纳入对数据湖状态的周期性评估。

写后优化(Optimize-After-Write)。 多个现有架构(Microsoft, 2025a;Goswami and Sarkar, 2023;Aguilar-Saborit 等,2024)通过在引擎内集成钩子(hook)的方式,在写入发生变化时自动触发压实,即把压实决策“”给引擎。同样可以使用前文所述的特征(traits)作为触发条件:当某个特征值超过阈值时,要么立即触发压实,要么由“写后优化”钩子通知自动压实服务“状态已变化,需要重新计算相关候选的特征”。立即触发可使表保持更接近最优状态,但需要不受限的压实预算;与之相对,将钩子与调度解耦能在资源使用上更灵活,允许受控的特征计算高效的任务执行

周期性压实(Periodic Compaction)。 相比直接修改引擎驱动,我们也可以将自动压实实现为独立服务(Syam, 2023;Apache Hudi, 2025b;Stormacq, 2023),并可与 OpenHouse 等目录/控制平面集成。该服务独立运行,周期性评估是否满足压实条件,通过“拉取”集群状态信息来安排压实任务。该方式特别适用于压实周期可预测的场景:例如在低峰时段安排压实以降低对集群的影响,或确保压实不干扰其他活跃工作负载。

image.png

这些策略可与 AutoComp 的工作流无缝集成(见图 5)。在这里,AutoComp 作为一个独立组件运行,同时支持 pushpull 两种方式:要么由钩子(hook)触发对候选特征的(重新)计算,要么周期性地从 OpenHouse 集群拉取信息并完成计算。

6. 压实框架评测(Evaluation of Compaction Framework)

本节基于合成工作负载评估 AutoComp,重点考察其在缓解 LST 小文件激增影响方面的有效性。

集群基础设施与配置(Cluster Infrastructure and Configuration)

实验在与 LinkedIn 生产环境相近的集群上进行:运行 Apache Spark v3.1.1Apache Iceberg v1.2.0 库。驱动与执行器节点使用标准配置,并启用 AQE(Adaptive Query Execution) (Apache Spark, 2025)。查询集群由 1 个 driver 节点 + 15 个 executor 节点组成;压实集群由 1 个 driver 节点 + 3 个 executor 节点组成。两套集群均通过 Azure VMSS 供给,节点规格为 Azure Standard E8s v3(Intel® Xeon® CPU E5-2673 v4 @ 2.30GHz,8 vCPU,64GB RAM)。OpenHouse v0.5.131 以其默认 Terraform 配置部署在独立的 AKS 集群上(OpenHouse, 2025)。AutoComp 扩展以周期性方式运行,并依据其决策逻辑触发 Spark 压实作业。实验数据存放在 Azure Data Lake Storage Gen2(ADLS) (Microsoft, 2025b)。除 Iceberg 元数据表(Apache Iceberg, 2025c)外,我们还使用 Logs Analytics(Microsoft, 2025e)监控各服务的遥测数据。

实验工作负载设计(Design of Experimental Workloads)

我们使用 CAB-gen 工具(van Renen and Leis, 2023;Cloud Analytics Benchmark Tool, 2025,简称 CAB)生成多库与查询流的元数据,模拟云数仓环境中的真实使用模式(Vuppalapati et al., 2020)。数据库模式基于 TPC-H,查询流覆盖:带正弦波动的稳定需求(如看板)、短突发(交互式查询)、大突发(日常维护作业)以及在特定时点触发的可预测负载(如按小时作业)。CAB-gen 需要若干参数:原始数据量、数据库数量、CPU 时间(总计算工作量)与实验持续时间。我们的设置为:500 GB 数据、20 个数据库、1 CPU 小时、5 小时实验时长。在用 CAB-gen 生成数据库定义后,我们使用 TPC-Hdbgen 工具(TPC, 2021)生成合成数据。将 lineitem 表按 shipdate粒度分区,从而在**分区表(lineitem)非分区表(orders)**之间形成混合的数据更新模式。^1
^1 原始 CAB-gen 仅对 orders 表生成更新;我们扩展为同时对 orderslineitem 生成更新。

候选选择与调度(Candidate Selection and Scheduling)

合成实验聚焦三种候选选择策略:
(i) 不进行压实
(ii) 表级(table-scope)压实
(iii) 混合策略:若表已分区则进行分区级(partition-scope)压实,否则回退为表级。
表级压实模拟当前 OpenHouse 的实现;混合策略用于考察分区级压实是否有助于平衡资源利用。在表级我们并行压实多个候选;在分区级我们顺序执行压实——这是因为我们观察到,即便目标是不同分区,并发压实仍可能因冲突被丢弃(详见 §4.4)。压实每 1 小时触发一次;因此在 5 小时窗口内,理想情况下应包含 4 次压实执行。

指标(Metrics)

为全面理解压实对工作负载执行的影响,我们同时采集客户端服务端统计。客户端侧关注查询执行时间与执行过程中的错误数量;服务端侧收集多项与压实相关的指标,包括当前文件数、重写字节数、新增文件数等。此外,我们计算自定义指标 GBHrApp\mathrm{GBHr}_{\text{App}},反映某个应用(App) 所需的计算资源(以作业为单位,每一次触发的压实操作视作一个独立实例)。

image.png

6.1 文件数量(File Count)

我们的首要目标是评估 AutoComp 在存储层处理 HDFS 小文件问题的有效性。我们在查询处理集群上运行 CAB 工作负载,同时对 20 个数据库的查询流并发执行;压实策略运行在独立的压实集群上,并以每 1 小时为间隔触发。图 6 展示了两种场景下文件数量随时间的变化:一是无压实的基线;二是采用 MOOP 策略(在“减少小文件的收益”与“重写表/分区的成本”之间做权衡)的 AutoComp。我们将每轮 AutoComp 压实的工作单元数量 (k) 设置为:表级压实 10 个;混合策略则为 50500 个;目标文件大小为 512 MB;MOOP 的权重设为 0.7(文件数减少)与 0.3(计算成本),以贴近我们的 OpenHouse 部署。需要说明的是,实际中可根据可用压实资源生产渐进上线需求调整 (k) 的取值。此处用于可视化的取值仅用于展示在一系列 (k) 值上可观察到的一致趋势

存储层变化(Storage Layer Changes)
基线(无压实)下,我们观察到初始文件数很高,因为数据装载会生成大量小文件——这在实践中很常见(如由集群错误配置引起,见 §2)。实验过程中,文件数持续上升,平均每小时增加约 2,640 个文件,但具体数值会随各时段内执行的写查询而波动。整体来看,实验平均运行约 5 小时;由于工作负载模式在第 4 小时附近对查询处理集群施加更大压力,该时段的数据写入会出现显著峰值。启用压实后,所有压实策略下文件数均出现显著下降:先是快速回落,随后曲线逐渐趋缓。对混合策略而言,下降曲线会更平缓,因为每轮被压实的实体较少,从而实现更渐进、可控的文件数下降。

压实成本(Compaction Cost)
虽然各策略都能降低文件数,但还需同时关注压实带来的成本。图 7 展示了实验期间,不同策略下压实的平均 GBHrApp\mathrm{GBHr}_{\text{App}} (应用级计算资源消耗)。当表的布局高度碎片化时,表级压实可能更有利且更高效;但采用更细粒度的方法(如混合策略中的分区级压实)则能提供更强的可控性,以更慢的节奏降低文件数,从而在时间维度上平衡资源使用——这一点也体现在各次压实操作之间更为稳定GBHrApp\mathrm{GBHr}_{\text{App}} 数值上。

image.png

image.png

image.png

image.png

6.2 查询性能(Query Performance)

小文件的激增会显著影响查询性能。为评估 AutoComp 对查询性能的作用,我们在实验全程记录了查询执行时间。图 8 对比了无压实与多种压实策略下的只读查询(左列)与读写查询(右列)的执行时长。每个“烛形柱”(更接近箱线图的含义)表示每小时的最小值、25 分位数、中位数、75 分位数与最大值。

先看只读查询:第 1 小时各策略表现接近;自第 2 小时起,开启压实能持续提升查询性能,其中更激进的压实策略(表级,top-10)使执行时间下降更快。同时,执行时长的离散度也在降低——更短的查询运行时间减轻了查询集群中的资源争用。对于相对温和的策略(混合,top-500),同样出现了显著改进,但幅度不及更激进策略,这与我们此前关于成功压实的文件数量、从而系统总文件数下降的观察一致。

需要注意的是:两种压实策略的实验端到端运行时间都满足预设的5 小时上限;而无压实的基线由于排队更长的查询执行额外增加了约 25 分钟的开销。

表 1. 每小时的客户端与集群端冲突数

小时写入查询数客户端冲突-无压实客户端冲突-表级(top-10)客户端冲突-混合(top-500)集群端冲突-表级(top-10)集群端冲突-混合(top-500)
2121114230
35020170
41515640
5840200

除查询用时外的重试行为分析。
除工作负载查询的执行时间外,我们还考察了由写写冲突引发的重试(见表 1)。其中包含两类:其一是客户端侧冲突——例如版本冲突导致客户端操作终止;其二是集群侧冲突——发生在压实操作期间。我们发现,即便不启用压实,由于对同一张表的并发写入,仍会出现冲突;并且这类冲突常与工作负载模式的峰值相关(可由某小时内的写查询数反映)。一个例外是我们的表级压实实验:由于早期压实操作数量较多,之后又出现陈旧元数据相关的冲突,导致在实验初段冲突更为明显。到第 5 小时时,存在写入活动的表(如 lineitemorders)基本已完成压实,写写冲突随之减少。更有意思的是,在混合策略下我们未观察到集群侧冲突,这表明待压实候选的粒度越小,被打断的压实操作发生概率越低——这与直觉一致。

6.3 自动调参与压实触发器(Auto-Tuning Compaction Triggers)

如前所述,自动压实的一大难点是为给定负载选择合适的参数阈值。因此,我们将一个自动调参框架与 AutoComp 结合进行实验,并采用简化的写后优化(optimize-after-write)钩子设置(即假定压实资源不受限)。我们选用两种压实特征——小文件数量文件熵(Syam, 2023)——对其触发阈值进行搜索与调优。

和前文一致,我们用 LST-Bench 部署三类内置负载:TPC-DS WP1(长跑型、频繁数据修改)、TPC-DS WP3(读写集群解耦:一套集群负责写,另一套负责读)以及 TPC-H。两套数据集均采用 Scale Factor = 100;实验在 16 节点 Spark 集群上运行(WP3 额外使用 7 节点 sidecar 集群承载写入),并以 Delta Lake v2.4.0 作为 LST。这说明 AutoComp 设计具有良好通用性,可支持多种 LST 实现。为优化参数,我们使用开源优化框架 MLOS(MLOS, 2025;Kroth 等,2024)中的 FLAML 优化器(Wang 等,2021),迭代搜索阈值。图 9 展示了结果:纵轴为端到端实验总时长,横轴为迭代轮次(每轮使用 MLOS 给出的阈值)。主要结论如下:

(i) TPC-H(图 9(b)) :默认设置(无自动压实)表现最佳。原因在于:压实会重写整张非分区表,代价较高;且其较长的数据修改阶段本就主导了总执行时间。相对地,TPC-DS WP1(图 9(a))在表过度碎片化后启用压实收益明显,合理应用时可将查询时间最多降低至 1/2。最后,TPC-DS WP3(图 9(d))持续从压实中获益,因为读写分离的集群降低了与其他查询的资源争用

(ii) 使用小文件数触发熵触发时,查询性能相近(见图 9(a)、9(c)),说明二者在合适阈值下可得到可比结果。需要强调的是,这里仅实验了单特征决策函数;若采用更复杂的方法(如同时考虑计算成本多目标排序函数),结果可能会有所不同。

image.png

image.png

image.png

image.png

总体而言,这些实验表明:对像 AutoComp 这样的压实框架进行**自动调参(auto-tuning)**是一个值得进一步探索的有前景方向,详见 §8 的讨论。

7. 生产环境中的 AutoComp 影响(AutoComp Impact in Practice)

如 §2 所述,LinkedIn 最初通过手动触发压实任务来缓解小文件问题。但这一做法在规模化场景下很快被证明不可行。为应对 LinkedIn 的 OpenHouse 部署中超过 3.5 万张表的压实挑战,我们按如下特性实现并落地了 AutoComp 的一个实例化方案。首先,我们将压实限定在表级,与既有的手工压实策略保持一致。其次,我们在 §4.2 提出的文件数减少估计器计算成本评估器的基础上,结合 §4.3 的 MOOP 排序函数进行决策。我们对 MOOP 的权重进行了调优以反映具体目标:依据数据库的配额使用率(以文件总数或命名空间对象数计)来调整文件数减少的权重 w1w_1。每个数据库代表与某一租户关联的一组逻辑表:

w1=0.5×(1+UsedQuotaTotalQuota)w_1 = 0.5 \times \Bigl(1 + \frac{\mathrm{UsedQuota}}{\mathrm{TotalQuota}}\Bigr)

其中,TotalQuota\mathrm{TotalQuota} 为分配给某数据库的 HDFS 命名空间配额(以文件系统对象数计),UsedQuota\mathrm{UsedQuota} 为当前已使用的配额。最后,我们实现了每日触发一次周期性调度策略,每次选择一组 (k) 个压实候选。在生产首次上线阶段,固定候选数量对保证可预期行为至关重要;随着时间推移,我们过渡为依据可用压实资源动态确定 (k)

结合我们在手工自动压实上的经验,以下是来自生产部署的若干观察:(i)单靠手工压实在生产是否足够;(ii)压实如何改变了 OpenHouse 中的文件分布;(iii)自动压实对用户工作负载执行与 HDFS 元数据操作的影响。

手工压实的收益递减(Diminishing Returns of Manual Compaction)。
早期的缓解方案是一种临时性的手工压实策略:以较高频率(如每日)反复压实一组固定的 k100k \approx 100 张表。这些表之所以被选中,是因为它们高度碎片化。初期结果非常显著:小文件数量减少、查询性能提升、存储开销下降。然而,这些收益会随时间递减。一旦小文件被合并,进一步压实带来的增益就很有限。图 2 显示,在手工压实的第二至第三个月之间,文件大小分布基本不再变化。总体上,我们观察到:在 LinkedIn 的 OpenHouse 部署中,并非所有表都能同等受益于压实——有些表以较低成本获得了显著收益,而另一些表则成本高、收益小。在实践中,识别“高影响力候选”并非易事,因为用户每天都在修改数据、创建新表、调整工作流。因此,人工定义压实目标并不理想,这也促使我们转向自动化方案。

image.png

image.png

image.png

部署压实机制(Deploying Compaction Mechanisms)
在 OpenHouse 中部署自动压实,大幅缓解了小文件问题。具体而言,在上线之前,用户经常遇到以下问题:(i)由于过多的 RPC 流量导致 HDFS 读取超时而引发的查询失败;(ii)用户 HDFS 命名空间配额频繁超限;(iii)对象数量快速增长,因而需要频繁进行 HDFS 联邦以分散负载。正如动机场景(图 2)所示,在定期执行压实任务之前,系统中 83% 的文件小于 128MB。当我们引入手动压实后,整体文件分布明显改善:小文件占比由 83% 降至 62% 。随后,我们将 AutoComp 逐步纳入 OpenHouse 的压实决策机制,进一步降低了小文件比例。我们起初以非常保守的 (k) 值部署 AutoComp(即 k10k \approx 10),以便在不打扰用户的前提下,密切观察压实对生产环境的影响。值得注意的是:即使从手动的 top-100 转为自动的 top-10 策略——即便每轮压实的表数量减少了 10×——整体的文件数下降反而更明显。更具体地,我们观测到:手动压实平均减少 659 万 个文件,而 AutoComp(top-10)平均减少 744 万 个文件,提升 12% 。图 10(a) 进一步给出了 6 周期间“文件数减少”与“压实成本(按应用计的 TB·小时,App TBHr)”之间的关系;在第 3 周,我们将策略从手动 k=100k=100 切换到自动 k=10k=10 ,有效性提升的同时计算成本也上升。图 10(b) 展示了自动压实部署到第 22 周时,从固定 (k) 过渡到受最大压实预算约束的动态 kk :在 226 TBHr 的预算下,我们每次自动压实迭代可成功压实约 k2500k \approx 2500 张表。总体来看,尽管部署规模持续扩大,自动压实机制仍然在一段时间内显著降低了 HDFS 的文件总数(见图 10(c))。

模型准确性与估算误差(Model Accuracy and Estimation Errors)
我们通过对比预测值实际值来评估估计器在“文件数减少”和“计算成本”两方面的准确性。不幸的是,二者偶尔会出现偏差。例如,我们曾将某次压实任务的计算成本估计为 108 TBHr,而实际消耗为 129 TBHr低估 19% );同时,对应的文件数减少被高估 28% 。这些不匹配表明:尽管当前模型在排序层面总体有效,但仍需进一步改进其精度——尤其是在分区边界的处理上。由于压实不会跨分区,按表级进行的估计可能会高估可合并的小文件数量。

image.png

image.png

压实对工作负载与 HDFS 的影响(Impact of Compaction on Workloads and HDFS)
我们还分析了与 AutoComp 协同运行的每日扫描密集型(scan-heavy)工作负载的表现。为评估周期性自动压实对此类负载的影响,我们绘制了该工作负载在执行期间被扫描的文件数量,并将其与查询执行时间查询成本(以 App TBHr 计)相关联,如图 11(a) 所示。该图基于最近 30 天窗口内由 AutoComp 选中的 1291 张唯一表,展示了归一化后的观测结果。

我们观察到:当一次压实运行降低了文件数量时,随后查询执行时扫描的文件数也随之下降。此外,扫描文件数的减少查询执行时间查询成本(App TBHr)的下降高度对应。然而,当某个周期内某些表未被 AutoComp 选中压实时,小文件会再次积累——图形上呈现反复出现的锯齿形模式。

总体来看,尽管部署规模随时间持续扩大,但在第 4 个月引入手动压实第 9 个月引入自动压实之后,HDFS 上的 filesystem open() 调用显著减少(见图 11(b))。第 4 个月出现的陡降与在一部分高度碎片化的表上引入手动压实相吻合:这些表平均包含 4200 万(42M)小文件,平均大小为 64MB。此前,这些表上的查询因对 NameNode 产生过量 RPC 流量而频繁发生 HDFS 读超时。这类超时常导致客户端同时重试,进一步加剧负载并触发**惊群(thundering herd)**问题。

8. 讨论与未来方向(Discussion and Future Directions)

借助 Apache Iceberg 等轻量化 LST 实现与 OpenHouse 这类控制平面在数据湖中心化架构中的部署,我们可以有效地定义并实施数据重组策略。通过在生产实践实验环境中探索自动压实问题,我们识别出若干值得进一步研究与创新的方向。

在多目标权衡中导航。 本文将文件压实建模为一个多目标优化任务,目标是最大化文件数减少最小化压实计算成本。当前方法通过加权求和得到单一解,权重反映当下优先级。这在实践中取得了不错效果,但将多目标折叠为单分数,天然存在偏重某一指标的风险;当系统条件、运维需求变化(如负载模式、资源可用性、某些数据库的特定需要),最佳平衡点也会移动。为应对该挑战,我们建议探索帕累托前沿(Pareto frontier) :不是收敛到单一“最优解”,而是生成一组帕累托最优解,每个解都体现了“文件数减少 vs. 计算成本”的一种独特平衡,且互不支配(改进一目标必然恶化另一目标)。同时,可利用机器学习中的回归分析实现动态权重估计,减少对固定权重的依赖。

冲突解决。 实践表明,理解 LST 的冲突解决机制并预测潜在冲突并不容易。比如在 OpenHouse 的实验中,我们发现即便是互不相交的分区,并发压实仍可能发生意外冲突,暗示冲突过滤实现上可能存在盲点。近期研究(包括形式化验证方法)正在填补 LST 冲突解决的认知空白(Vanlightly, 2024b,c,a)。AutoComp 已将调度单独拆出,以支持多样化的 LST 冲突处理策略;但引擎在压实等维护任务中的特定行为可能仍需补充扩展。

自动数据布局优化。 压实主要面向小文件与碎片治理,但可扩展到更广泛的布局优化。例如 Z-ordering / V-ordering(Powers, 2023b;Microsoft, 2025d;Kudinkin & Meng, 2021)可通过相关数据同置提升压缩比、编码效率与查询性能。它们与压实互补,可并入 AutoComp 的决策流程。这要求对候选生成特征计算进行扩展:部分优化在文件级施行,另一些在分区/表级实施,需在候选生成时考虑不同作用粒度;特征也要同时刻画收益(如更佳压缩、过滤效率)与成本(如抽样或多次扫描带来的开销)。

工作负载感知。工作负载感知纳入特征计算,可使 AutoComp 的决策更贴合查询模式与访问频率,进一步改进查询性能。同时,基于查询模式选择的分区/聚簇策略也会影响写入与压实效率,有助于减少不必要的数据冲突错误(Vanlightly, 2024b)。因此,布局优化策略的选择既要考虑查询负载,也要兼顾其对压实与冲突解决的更广泛影响。

写入与压实机制/策略的调优。 各类引擎与 LST 暴露了大量影响写时布局的配置参数。例如,Spark 的 AQE 可能在最终写入阶段选择过小的 shuffle 分区不佳的分布模式,从而产生过多小文件(Okolnychyi et al., 2024)。在像 LinkedIn 这样的组织里,工程师未必能统一掌控所有工作负载的引擎配置;因此像 OpenHouse 这样的控制平面提供了分析与暴露问题的机会,并向相关方输出可执行建议以便人工缓解。另一方面,LST 的压实任务与 AutoComp 自身也提供了会影响自动压实行为的可配置参数(§6.3)。我们的实验提示:“一刀切并不适用”:压实触发器与数据布局策略最好按工作负载定制,而不是对所有引擎统一标准。但工作负载级自动调参计算代价高——每次迭代需要数小时并消耗大量集群资源。缩短试验时间、降低计算成本是让自动调参在实践中可行的关键。

9. 相关工作(Related Work)

随着在通用分布式存储上引入类似 DBMS 的结构,自动压实研究愈发重要。早期工作(Severance & Lohman, 1976)提出用增量文件(delta files)缓解更新导致的写放大,这一概念如今已成为 LST 的核心。

数据库碎片整理。 Sears & van Ingen (2007) 在 DBMS 语境下分析了对象大小数据碎片化对系统性能的影响,指出两点关键结论:其一,最优数据布局与工作负载相关;其二,碎片会随时间显著拖慢性能。传统 DBMS 既有在线也有离线的整理方法。在线方法包含人工监督的重组:如 Narasayya & Syamala (2010) 提出基于 what-if API 评估收益的在线索引碎片整理,其范围级整理与 AutoComp 的细粒度压实相似——系统给出建议,但最终由 DBA 调度/触发。与之相对,离线方法(AutoComp 采用的是此类思路)依赖自动算法进行重组。Kolovson & Stonebraker (1989) 提出多级索引结构:将可变数据存磁盘、归档数据WORM 光盘,使用基于大小的算法触发 vacuum 迁移,以同时优化读写时延并降低存储成本。现代内存数据库(Diaconu et al., 2013;Sikka et al., 2012;Arulraj et al., 2016)采用类似原则:分别维护写优化区读优化区,并以大小/时间阈值触发迁移。Sears & Ramakrishnan (2012) 进一步提出 bLSM,结合 B-Tree 与 LSM 的特性,用 spring-and-gear 调度在各层间平衡压实,保障吞吐与延迟的可预测性。近期研究也系统探索了 LSM 压实的设计空间,在不同策略与负载间进行权衡分析(Sarkar et al., 2021)。如 Hudi 与较新的 Apache Paimon(孵化中)将这些原则(写/读优化区与自动压实)直接纳入其核心实现。

数据湖中的自动压实。 部分运行在数据湖上的引擎虽未将其表格式以可跨引擎互操作的 LST 形式公开,但采用了相似技术,在存储层仍会产生大量小文件。Apache Hive(Camacho-Rodríguez et al., 2019)在 HDFS 上引入 ACID 表,按delta 文件数碎片比阈值触发压实,并将清理(cleaning)合并(merging)阶段分离以减少对查询的干扰,与 LST 的技术相近。Nova(Olston et al., 2011)为 Apache Pig 工作流实现了类似的压实与清理任务,但缺少自动化,依赖手动触发Ahmad & Kemme (2015)HBase 提出独立压实服务器,将压实与用户负载隔离以提升系统效率。我们在合成实验与 LinkedIn 生产中的 AutoComp 部署采用了相似的理念,但 AutoComp集群选择与运行模式上更灵活,能适配多样的工作负载与系统需求。

LST 的自动布局调优。 自动调优机制已成为 LST 的关键挑战。近期工作(Syam, 2023;Goswami & Sarkar, 2023;Microsoft, 2025a;Aguilar-Saborit 等,2024;Apache Hudi, 2025b;Stormacq, 2023;Barr, 2024)强调需要灵活的方案应对数据布局难题AutoComp 在此基础上更进一步,作为首个面向自动压实的综合性方案,强调在算法、模型与运维场景上的可适配性,确保能与多样化的负载与基础设施协同工作。

10. 结论(Conclusion)

本文介绍了 AutoComp——一个用于应对小文件激增这一数据湖基础设施中常见问题的自动化压实框架。AutoComp 的设计同时遵循我们在 LinkedIn 部署实践中总结的功能性非功能性要求;通过合成负载真实生产环境的实验,我们验证了其有效性。我们观察到,诸如多目标优化函数面向工作负载的压实策略与调度等关键特性,能够显著提升压实效果,不仅对存储层带来积极影响,也改善了查询性能。此外,我们还概述了更广泛的数据布局优化方向中的多项后续研究机会,我们相信这些工作将持续有效地增强数据湖能力。