与文件系统和关系数据库一样,除非经过密切管理,否则数据会分散,从而导致计算成本过高来读取数据。 Delta Lake 不是例外。 应定期将数据文件重写为最佳布局,以减少单个文件作成本、改进数据压缩和优化读取器并行度。 该 OPTIMIZE 命令解决了这一难题:它将分区中的小文件分组到 理想的目标 文件大小的箱中,并将其重写到存储中。 结果是相同的数据被压缩到更少的文件中。
压缩方法
Microsoft Fabric 提供了几种在 Delta 表中保持最佳文件大小的方法:
OPTIMIZE 命令
该 OPTIMIZE 命令是压缩Delta表的基础操作。 它将小文件重写为较大的文件,以提高 Delta 表中的数据布局。
| 资产 | Description | 默认值 | 会话配置 |
|---|---|---|---|
| minFileSize | 小于此阈值的文件将分组在一起,并重写为较大的文件。 | 1073741824 (1 克) | spark.databricks.delta.optimize.minFileSize |
| maxFileSize | 命令生成的 OPTIMIZE 目标文件大小。 |
1073741824(1克) | spark.databricks.delta.optimize.maxFileSize |
重要
虽然OPTIMIZE是幂等操作(这意味着连续运行两次不会重写任何数据),但使用相对于Delta表大小过大的minFileSize可能会导致写入放大,使操作的计算成本高于必要。 例如,如果 minFileSize 设置为 1-GB,并且表中有一个 900 MB 的文件,那么在向表写入小型 1 KB 文件后 OPTIMIZE ,将重新编写大小合理的 900 MB 文件。 有关如何自动管理文件大小的指导,请参阅 自适应目标文件大小 文档。
OPTIMIZE 与 Z-Order 配合使用
ZORDER BY指定子句时,OPTIMIZE 会重新组织所有活跃文件,以便将 Z 顺序列中相似值的行集中在同一文件中,从而提高涉及这些列的查询跳过文件的效率。 在以下情况下使用 Z 顺序:
- 查询经常同时筛选两列或更多列(例如日期 + 客户ID),
- 这些谓词的选择性足够高,使得文件级跳过能够减少扫描的文件数量。
OPTIMIZE dbo.table_name ZORDER BY (column1, column2)
OPTIMIZE 使用 V-Order
该 VORDER 子句将生成作用域为压缩的文件,并应用 V 顺序优化。 有关 V 顺序的详细信息,请参阅详细 文档。
OPTIMIZE dbo.table_name VORDER
OPTIMIZE 使用液体聚类分析
液体聚类分析指定为表选项;有关详细信息,请参阅 启用液体聚类 分析。 启用液体聚类分析后, OPTIMIZE 执行应用聚类分析策略的物理重写。
重要
仅在启用了液体聚集功能的表上运行时,数据才会被聚集。 常规写入作不会对数据进行群集化。 使用压缩策略(例如自动压缩或手动调度优化作业)对于确保能够充分利用集群数据的优势(即增强 Delta 文件的跳过能力)至关重要。
快速优化
快速优化功能可以智能分析 Delta 表文件,并跳过那些不太可能有意义地提高性能的压缩操作。
快速优化会评估每个候选组(小文件组)是否满足可配置的最佳实践压缩目标,而不是盲目地压缩文件。 如果合并文件可能会达到您设定的最小目标大小,或者存在太多小文件,快速优化仅对文件组进行压缩。 否则,它会跳过该组或减少压缩的文件数。
根据您的压缩期望,可以对快速优化进行微调:
| 资产 | Description | 默认值 | 会话配置 |
|---|---|---|---|
| minNumFiles | 如果箱中没有足够的估计数据来生成 压缩 文件,则需要在箱中存在的小型文件数,以便进行优化。 | 50 | spark.microsoft.delta.optimize.fast.minNumFiles |
| parquetCoefficient | 乘以优化上下文最小文件大小,以确定压缩范围内必须存在于箱中的最小小型文件数据量。 | 1.3 | spark.microsoft.delta.optimize.fast.parquetCoefficient |
注释
结果 parquetCoefficient ,箱的目标大小大于优化上下文的最小目标文件大小。 此系数考虑到合并多个小型 parquet 文件可以实现更好的压缩,因此数据量小于小文件的总和。 此值可以增大,以更保守的方式减少快速优化跳过分区的频率,或缩小以允许更宽松的分区跳过。
工作原理
快速优化会在压缩箱之前引入额外的检查。 对于每个候选桶,快速优化进行评估:
- 箱中原始数据的估计量(小文件大小之和)
- 是否估计合并小文件以生成满足配置的最小目标大小的文件
- bin 至少包含配置的最小数量的小文件吗
快速优化会评估每个小型文件箱,并仅压缩可能达到最小目标大小或超过最小文件计数的小文件。 不满足这些阈值的箱将被跳过或部分压缩。 跳过欠佳的 bin 可减少不必要的重写、降低写入放大,并使 OPTIMIZE 作业更具幂等性。
注释
确切的实现可能会随着时间推移而演变。
快速优化可能会导致在 Delta 表生命周期内重写的数据更少。 如下图所示,快速优化会跳过压缩次优箱。净结果更快、更幂等 OPTIMIZE ,写入放大更少。
注释
出于说明目的,上图假定从压缩写入的文件的大小是小文件的大小之和。 这也意味着 parquetCoefficient 为1。
局限性
- 不适用于液体聚类分析和 Z 顺序操作
- 快速优化不会修改自动压缩的行为
文件级压缩目标
为了避免因更改压缩最小和最大文件大小目标而对先前认为已压缩(足够大)的数据进行重新压缩,可以启用spark.microsoft.delta.optimize.fileLevelTarget.enabled 来防止已压缩文件的重新压缩。 启用后,如果文件在压缩时至少满足目标文件大小的一半,则不会重新编译文件。 维护文件级别目标可最大程度地减少写入放大,因为压缩目标大小会随着时间的推移而变化(例如,通过评估自适应目标文件大小并设置更大的目标)。 如果启用,当运行 OPTIMIZE 或设置delta.targetFileSize或delta.targetFileSize.adaptive表属性时,OPTIMIZE_TARGET_SIZE标记会被添加到新文件中或在任何写入操作时。
注释
虽然默认情况下未启用,但Microsoft建议启用 文件级压缩目标 以限制潜在的写入放大。
自动压缩
每次写入操作完成后,自动压实都会评估分区健康状况。 当它检测到分区中存在过多文件碎片(太多小文件)时,会在写操作完成后立即触发同步 OPTIMIZE 操作。 这种编写器驱动的文件维护方法是最佳的,因为压缩仅在以编程方式确定有利时执行。
设置在会话级别以在新表上启用自动压缩:
在表级别设置,仅对特定表启用:
CREATE TABLE dbo.table_name
TBLPROPERTIES ('delta.autoOptimize.autoCompact' = 'true')
使用 DataFrameWriter 选项以在新表上启用:
df.write.option('delta.autoOptimize.autoCompact', 'true').saveAsTable('dbo.table_name')
对现有表启用:
ALTER TABLE dbo.table_name
SET TBLPROPERTIES ('delta.autoOptimize.autoCompact' = 'true')
可以通过以下 Spark 会话配置来优化自动压缩的行为:
| 资产 | Description | 默认值 | 会话配置 |
|---|---|---|---|
| maxFileSize | 压缩文件的目标最大文件大小(以字节为单位)。 | 134217728b (128 MB) | spark.databricks.delta.autoCompact.maxFileSize |
| minFileSize | 要视为压缩的文件的最低文件大小(以字节为单位)。 此阈值以下的任何内容都被视为压缩,并计入 minNumFiles 阈值。 |
默认情况下未设置,计算结果为maxFileSize的一半,除非显式设置值。 |
spark.databricks.delta.autoCompact.minFileSize |
| minNumFiles | 在触发自动压缩的阈值下 minFileSize 必须存在的最小文件数。 |
50 | spark.databricks.delta.autoCompact.minNumFiles |
注释
Microsoft建议使用 自动压缩 而不是计划 OPTIMIZE 作业。 自动压缩通常优于计划压缩作业,以最大程度地提高读/写性能,并且通常可以减少与编码、计划以及调整计划作业运行频率相关的维护负担。 当数据处理的服务级别目标能够容忍因需要时触发自动压缩而带来的附加延迟时,建议使用自动压缩。 如果数据延迟要求严格,将优化调度安排在单独的 Spark 池上运行可能更有效,这样写入操作就不会因触发同步压缩操作而出现周期性峰值。
重要
虽然压缩是采用的关键策略,但它也应该与避免通过优化写入等功能 编写小文件 进行适当配对。 有关详细信息,请参阅优化写入的指导。
湖屋表维护
用户可以从 Lakehouse UI 运行诸如 OPTIMIZE 之类的临时维护操作。 有关详细信息,请参阅 Lakehouse 数据表维护。
最佳做法摘要
- 为摄取管道启用自动压缩,其中包含频繁的小规模写入(流式处理或微批处理),以避免手动调度并确保文件自动压缩。
- 对于其他写入模式,启用此选项可以作为防范累积小文件问题的保险,但需要权衡您的数据处理服务级别目标是否能够忍受处理时间的周期性峰值。
- 在需要重写多个分区或运行 Z-Order 时,可以在 安静时段安排全表操作
OPTIMIZE。 - 启用 快速优化 以减少写入放大并使
OPTIMIZE更具幂等性。 - 启用 文件级压缩目标 ,以防止随着表的大小增长并使用更大的目标文件大小而进行写入放大。
- 请记住,预写入压缩(优化写入)的成本低于写入后压缩(优化)。 有关最佳做法,请参阅 优化写入 文档。