优化数据文件布局

OPTIMIZE 命令重写数据文件以改善 Delta 表的数据布局。 对于启用了 liquid 聚类分析的表,OPTIMIZE 会重写数据文件以按 liquid 聚类分析键对数据进行分组。 对于定义了分区的表,文件压缩和数据布局在分区内执行。

未启用 liquid 聚类分析的表可以选择包含 ZORDER BY 子句,以改进重写时的数据聚类分析。 Databricks 建议使用 liquid 聚类分析,而不要使用分区、ZORDER 或其他数据布局方法。

请参阅 OPTIMIZE

语法示例

通过运行 OPTIMIZE 命令触发压缩:

SQL

OPTIMIZE table_name

Python

from delta.tables import *
deltaTable = DeltaTable.forName(spark, "table_name")
deltaTable.optimize().executeCompaction()

Scala

import io.delta.tables._
val deltaTable = DeltaTable.forName(spark, "table_name")
deltaTable.optimize().executeCompaction()

如果拥有大量数据,并且只想要优化其中的一个子集,则可以使用 WHERE 指定一个可选的分区谓词:

SQL

OPTIMIZE table_name WHERE date >= '2022-11-18'

Python

from delta.tables import *
deltaTable = DeltaTable.forName(spark, "table_name")
deltaTable.optimize().where("date='2021-11-18'").executeCompaction()

Scala

import io.delta.tables._
val deltaTable = DeltaTable.forName(spark, "table_name")
deltaTable.optimize().where("date='2021-11-18'").executeCompaction()

注意

  • 二进制打包优化幂等,这意味着如果在同一数据集上运行两次,则第二次运行不起作用。
  • 二进制打包旨在根据其在磁盘上的大小生成均匀平衡的数据文件,但不一定是每个文件的元组数。 但是,这两个度量值通常是相关的。
  • Databricks Runtime 11.3 LTS 及更高版本提供用于执行 OPTIMIZE 操作的 Python 和 Scala API。

Delta 表的读取器使用快照隔离,这意味着,当 OPTIMIZE 从事务日志中删除不必要的文件时,它们不会中断。 OPTIMIZE 不会对表进行任何数据相关更改,因此,在 OPTIMIZE 之前和之后读取都具有相同的结果。 对作为流式处理源的表执行 OPTIMIZE 不会影响将此表视为源的任何当前或未来的流。 OPTIMIZE 返回所删除文件的文件统计信息(最小值、最大值、总计等)和操作添加的文件。 优化统计信息还包含 Z 排序统计信息、批处理数和已优化分区数。

你还可以使用自动压缩来自动压缩小文件。 请参阅 Azure Databricks 上的 Delta Lake 的自动压缩

我应该多久运行一次 OPTIMIZE

对 Unity Catalog 托管表启用预测优化,以确保 OPTIMIZE 在经济高效时自动运行。

如果选择运行 OPTIMIZE 的频率,则会在性能和成本之间进行权衡。 为了提高最终用户查询性能,请更频繁地运行 OPTIMIZE。 由于资源使用量增加,这将产生更高的成本。 若要优化成本,请减少运行频率。

Databricks 建议从每天运行一次 OPTIMIZE 开始,然后调整频率以平衡成本和性能权衡。

运行 OPTIMIZE(二进制打包和 Z 排序)的最佳实例类型是什么?

这两个操作都是执行大量 Parquet 解码和编码的 CPU 密集型操作。

Databricks 建议使用计算优化实例类型。 此外,OPTIMIZE 也受益于附加的 SSD。