调整 Delta 表数据文件的大小

适当大小的文件对于查询性能、资源利用率和元数据管理非常重要。 较小的文件会增加任务开销和元数据操作,而较大的文件可能无法充分利用并行性,并导致 I/O 不均衡。 Delta Lake 使用文件元数据进行分区修剪和数据跳过,因此以正确的文件大小为目标可确保高效的读取、写入和维护。

以下部分演示如何使用各种不同的文件大小优化功能来实现 Delta 表的性能。

可调整的数据布局操作

Optimize

OPTIMIZE 命令将小型文件重写为较大的文件,以提高 Delta 表中数据的布局。 有关包括文件大小优化信息的更多详细信息,请查看 OPTIMIZE 命令 文档。

自动压缩

每次写入操作后,自动压缩会自动评估分区的健康状况。 当它检测到分区中存在过多文件碎片(太多小文件)时,会在写操作完成后立即触发同步 OPTIMIZE 操作。 这种编写器驱动的文件维护方法通常是最佳的,因为压缩仅在以编程方式确定有利于时执行。 有关详细的配置选项和其他信息,请参阅 自动压缩 文档。

优化写入

通过执行预写入压缩(bin 打包),优化写入可减少小文件的开销,从而生成更少但更大的文件。 在 Spark 写入 Parquet 文件之前,此方法将内存中数据随机化为大小最佳的箱,从而最大程度地提高生成适当大小的文件的潜力,而无需立即执行写入后清理作。

应谨慎使用优化写操作,因为数据重排的计算成本可能会给特定的写入场景增加过多和不必要的处理时间。 当写操作会生成小文件时,优化写入非常有用,这些小文件可能会成为后续压缩的对象。

该屏幕截图显示了如何优化写入操作结果,从而减少写入的文件数量。

优化写入通常有利于:

  • 分区表
  • 具有频繁小插入的表
  • 可能会接触多个文件的操作(MERGEUPDATEDELETE

对于特定表上的选择性应用程序,请取消设置会话配置并单独启用表属性。 取消设置会话级别配置允许 Spark 会话延迟每个表,以确定是否应应用优化写入。

  1. 取消优化写入设置

    spark.conf.unset("spark.databricks.delta.optimizeWrite.enabled")
    
  2. 在单个表上启用

    ALTER TABLE dbo.table_name
    SET TBLPROPERTIES ('delta.autoOptimize.optimizeWrite' = 'true')
    

要在 Spark 会话中启用向所有分区表进行的写入操作,请确保会话配置处于默认状态,然后启用会话配置 spark.microsoft.delta.optimizeWrite.partitioned.enabled

SET spark.microsoft.delta.optimizeWrite.partitioned.enabled = TRUE

可以通过spark.databricks.delta.optimizeWrite.binSize配置选项调整优化写入生成的目标文件大小。

注释

有关 资源配置文件 的默认优化写入设置,请参阅资源配置文件。

一致地设置目标文件大小

为了避免需要设置最小和最大目标文件大小会话配置以优化、自动压缩和优化写入,Microsoft Fabric 提供 delta.targetFileSize 表属性作为统一表级别的所有相关数据布局配置的方法。 目标文件大小值以字节字符串的形式输入(例如,、1073741824b1048576k1024m1g)。 指定后,它优先于所有其他会话配置和自适应目标文件大小。

ALTER TABLE dbo.table_name
SET TBLPROPERTIES ('delta.targetFileSize' = '256m')

自适应目标文件大小

Microsoft Fabric 提供自适应目标文件大小,以消除与通过 delta.targetFileSize 表属性手动调整会话或单个表中所有表的目标文件大小相关的复杂性。 自适应目标文件大小使用 Delta 表启发式方法(例如表大小)来估计理想目标文件大小,并在条件变化时自动更新目标,确保最佳性能,无需手动干预或维护开销。

注释

虽然目前默认未启用,但Microsoft建议启用 自适应目标文件大小 会话配置。

通过设置以下 Spark 会话配置,在 Spark 会话中创建或修改的表上启用自适应目标文件大小:

SET spark.microsoft.delta.targetFileSize.adaptive.enabled = TRUE

启用后,将在以下方案中评估并设置自适应目标文件大小:

  • CREATE TABLE AS SELECTCREATE OR REPLACE TABLE AS SELECT 操作
  • 覆盖写入(例如, DataFrame.write.mode("overwrite")INSERT OVERWRITE
  • ErrorIfExistsAppendIgnore模式下创建新表时写入
  • OPTIMIZE 命令的开头

设置后,在每次 OPTIMIZE 操作开始时,理想的大小会继续重新评估,以确保当前的启发式方法反映最新的数据分布和表的增长。 这种自适应方法会随着时间推移自动更新目标文件大小,无需手动优化,同时随着数据的增长而保留查询和写入性能。 当需要锁定特定大小(例如在超优化或测试用例中),可以通过显式设置用户定义的 delta.targetFileSize 表属性来替代自适应设置。

可以通过在表格上运行 DESCRIBE DETAILDESCRIBE EXTENDED 来审计评估后的自适应目标文件大小值。 自适应评估大小以字节字符串的形式存储在表属性 delta.targetFileSize.adaptive中。 此值用作优化、自动压缩和优化写操作中的最大或目标大小配置参数。 相关配置使用的最小值计算为delta.targetFileSize.adaptive的一半。

可以通过以下 Spark 会话配置进一步配置自适应目标文件大小:

资产 Description 默认值 会话配置
minFileSize 将最小文件大小(下限)指定为自适应目标文件大小在计算时使用的字节字符串。 必须介于 128 MB 和 1 GB 之间。 128m spark.microsoft.delta.targetFileSize.adaptive.minFileSize
maxFileSize 将最大文件大小(上限)指定为自适应目标文件大小在计算时使用的字节字符串。 必须介于 128 MB 和 1 GB 之间。 1024m spark.microsoft.delta.targetFileSize.adaptive.maxFileSize
stopAtMaxSize true计算出的目标文件大小达到maxFileSize时,停止进一步的大小评估,从而减少对非常大表的任何计算开销。 spark.microsoft.delta.targetFileSize.adaptive.stopAtMaxSize

注释

启用 stopAtMaxSize 后(默认值),自适应目标大小在达到最大值时保持固定,避免额外的计算。 如果表在增长后可能会缩小,请将此属性设置为 false 允许重新计算低于最大阈值。

下图说明了表格尺寸与理想的 Parquet 文件大小之间的关系。 对于低于 10 GB 的表,Fabric Spark 运行时将目标文件大小评估为 128 MB。 随着表大小的增长,目标文件的大小会线性增加,对于超过10 TB的表,目标文件大小可能达到 1 GB。

展示表格大小与最佳 parquet 文件大小之间关系的图表。

从 128MB 开始的小规模,然后随着表的大小增长而调整 parquet 文件的大小,这具有级联优势:

  • 改进了 Delta 文件跳过:大小正确的文件支持最佳的数据群集和跳过,从而允许 Delta 的文件跳过协议在查询执行期间消除更多无关文件。 包含 128MB 文件的小型表(而不是 1GB 文件)允许跳过 8 倍的可能文件。

  • 降低更新成本MERGEUPDATE 操作仅重写受影响的文件。 大小适中的文件可以减少每次操作所涉及的文件数,从而减少重写的数据量。 启用删除向量后,适当的文件大小变得至关重要:超大文件中的行级墓碑标记会导致在压缩或清除操作期间产生大量清理成本。

  • 优化并行度:大小正确的文件使 Spark 能够实现理想的任务并行度。 过多的小文件使计划程序不堪重负;过少的大文件则导致 Spark 池未能充分利用。 最佳大小调整可最大化读取和写入吞吐量。

自适应目标文件大小可以通过选择比默认值更佳的文件大小,将压缩性能提高30-60%,并提供更快的查询和写入速度。 如果自适应评估生成与默认 Spark 会话配置相同的大小,则不会有预期的性能改进。

重要

为了避免写放大——即当适应性目标文件大小随着表的增长而增加时重新写入已压缩的文件,请启用 文件级别压缩目标。 此功能可防止在以前的自适应目标大小下压缩的文件不必要地重新压缩。 有关详细信息,请参阅 有关文件级压缩目标的文档。

最佳做法摘要

  • 启用自动压缩,以在包含频繁小写入(流式处理或微批处理)的引入管道中避免手动计划,并保持文件自动压缩。
    • 对于其他写入模式,启用它可能有助于防止累积小型文件,类似保险,但需认真考虑数据处理服务水平目标是否能容忍处理时间的周期性峰值。
  • 启用自适应目标文件大小 以删除围绕最佳目标文件大小的猜测。
  • 在受控引入路径中使用优化写入 (批处理作业可以容忍随机、分区方案或频繁的小写入),以减少创建小型文件和下游维护成本。 预写压缩(优化写入)的成本往往低于写入后压缩(优化)。
  • 在静默时段期间,计划全表操作,例如必须重新编写多个分区或运行 Z-Order。
  • 启用 快速优化 以最大程度地减少写入放大并使其 OPTIMIZE 更幂等(请参阅 快速优化)。
  • 使用 delta.targetFileSize 或最好 是自适应目标文件大小 ,使目标文件大小值在数据布局功能和 Spark 会话中保持一致。
  • 启用 文件级压缩目标 ,以防止随着表的大小增长并使用更大的目标文件大小而进行写入放大。