数据组织优化

本文为您介绍Delta Table在数据组织优化服务上的架构设计。

Clustering

  • 当前痛点

    Delta Table支持分钟级近实时增量数据导入,高流量场景下可能会导致增量小文件数量膨胀,从而引发存储访问压力大、成本高,并且大量的小文件还会引发Meta更新以及分析执行慢,数据读写I/O效率低下等问题,因此需要设计合理的小文件合并服务,即Clustering服务来自动优化此类场景。

  • 解决方案

    Clustering服务主要由MaxCompute内部的Storage Service来负责执行,专门解决小文件合并的问题,但它并不会改变任何数据的历史中间状态,即不会消除任何一条记录数据的中间历史状态。

  • Clustering服务流程

    Clustering服务的整体操作流程如图所示。

    image.png

    • Clustering策略的制定主要基于典型的读写业务场景,会周期性地根据数据文件的大小、数量等多个维度进行综合评估,并进行分层次的合并。Level0~Level1阶段主要针对原始写入的DeltaFile(图中蓝色数据文件)进行合并,形成中等大小的DeltaFile(图中黄色数据文件)。当中等大小的DeltaFile达到一定规模后,会进一步触发Level1~Level2的合并,生成更大的DeltaFile(图中橙色数据文件)。

    • 针对超过一定大小的数据文件,将进行专门的隔离处理,以避免触发进一步的合并,从而避免不必要的读写放大问题。例如:Bucket3的T8数据文件所示。另外,对于超过一定时间跨度的文件也不会进行合并,因为将时间跨度太大的数据合并在一起可能导致在进行Time Travel或者增量查询时读取大量不属于此次查询时间范围的历史数据,进而造成不必要的读放大问题。

    • 由于数据是按照BucketIndex来切分存储的,因此Clustering服务会以Bucket粒度来并发执行,大幅缩短整体运行时间。

    • Clustering服务会与Meta Service进行交互,以获取待处理的表或分区列表。完成操作后,会将新旧数据文件的信息传入Meta Service。Meta Service在此过程中起到关键作用,它负责进行事务冲突检测,协调新旧文件Meta信息的无缝更新以及安全地回收旧数据文件。

    • Clustering服务能有效解决大量文件引发的读写效率低下的问题。由于每次执行至少需要读写一遍数据,将会消耗计算和I/O资源,存在一定的读写放大问题,当前MaxCompute引擎能够根据系统状态自动触发执行,以确保Clustering服务的高效执行。

Compaction

  • 当前痛点

    Delta Table支持Update和Delete格式的数据写入。如果存在大量此格式的数据写入,会导致中间状态的冗余记录过多,增加存储和计算成本,降低查询效率等问题。因此,需要设计合理的Compaction服务,以消除中间状态并优化这种场景。

  • 解决方案

    Compaction服务主要由MaxCompute内部的Storage Service来负责执行,既支持手动执行SQL语句触发,也可通过配置表属性按照时间频率、Commit次数等维度自动触发。此服务会把选中的数据文件,包含BaseFile和DeltaFile,一起进行Merge,消除数据的Update和Delete中间状态,PK值相同的多行记录只保留最新状态的一行记录,最后生成新的只包含Insert格式的BaseFile。

  • Compaction服务流程

    Compaction服务的整体操作流程如下所示。

    image.png

    • 在t1~t3时间段内,一批DeltaFile被写入,触发Compaction操作,以Bucket粒度并发执行,将所有的DeltaFile进行Merge,然后每个Bucket会生成新的BaseFile。随后在t4和t6时间段,又写入了一批新的DeltaFile,再次触发Compaction操作,将当前存在的BaseFile和新增的DeltaFile一起进行Merge操作,重新生成一个新的BaseFile。

    • Compaction服务还需要与Meta Service进行交互。其流程与Clustering类似,需要获取需要执行此操作的表或分区的列表。执行结束后,将新旧数据文件的信息传入Meta Service。其中,Meta Service负责Compaction操作的事务冲突检测、新旧文件Meta信息的原子更新以及旧数据文件的回收等工作。

    • Compaction服务通过消除记录的历史状态以节省计算和存储资源,提升全量快照查询的效率。然而,频繁执行Compaction需要大量计算和I/O资源,并可能导致新BaseFile占用额外存储,历史DeltaFile文件可能会被用于Time Travel查询,不能立即删除,将继续产生存储成本。因此,应根据具体业务需求和数据特性来决定Compaction操作的执行频率。在Update和Delete操作频繁以及全量查询需求高的情况下,可以考虑增加Compaction的频率以优化查询速度。

数据回收

由于Time Travel和增量查询都会查询数据的历史状态,因此需要保存一定的时间,可通过表属性acid.data.retain.hours来配置保留的时间范围。如果历史状态数据存在的时间早于配置值,系统会开始自动回收清理,一旦清理完成,Time Travel就查询不到对应的历史状态了。回收的数据主要包含操作日志和数据文件两部分。

同时,也会提供purge命令,用于特殊场景下手动触发强制清除历史数据。

需要特别说明的是,对于Delta Table,如果用户一直写入新的DeltaFile,那永远也删除不了任何一个DeltaFile,因为其他的DeltaFile可能对它有状态依赖。只有执行COMPACTION或者InsertOverwrite操作后,之后产生的数据文件对之前的那些DeltaFile就没有依赖了,如果超过Time Traval可查询的时间周期后,就可以被删除了。

对于用户就是一直不执行Compaction操作的极端场景,引擎侧会做一些优化避免产生无限的历史记录,后台系统会周期性地对超过Time Travel时间的BaseFile或者DeltaFile进行自动Compaction,后续就可以正常回收这些被Compaction的历史数据文件。