该 OPTIMIZE 命令重写数据文件,以提高 Delta Lake 和 Apache Iceberg 表的数据布局。 对于启用了 liquid 聚类分析的表,OPTIMIZE 会重写数据文件以按 liquid 聚类分析键对数据进行分组。 对于定义了分区的表,文件压缩和数据布局在分区内执行。
不带液体聚类分析的 Delta Lake 表可以选择包含一个 ZORDER BY 子句,以改进重写时的数据聚类分析。 Apache Iceberg 表使用聚类分析和排序策略,而不是 ZORDER。 Databricks 建议使用 liquid 聚类,而不要使用分区、ZORDER 或其他数据布局方法。
请参阅 OPTIMIZE。
Important
在 Databricks Runtime 16.0 及更高版本中,可以使用 OPTIMIZE <table_name> FULL 强制对启用 liquid 聚类分析的表重新聚类。 请参阅 强制重聚类化。
语法示例
通过运行以下命令 OPTIMIZE 触发压缩:
SQL
OPTIMIZE table_name
Python
Python DeltaTable API 特定于 Delta Lake。
from delta.tables import *
deltaTable = DeltaTable.forName(spark, "table_name")
deltaTable.optimize().executeCompaction()
Scala
Scala DeltaTable API 特定于 Delta Lake。
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
Python DeltaTable API 特定于 Delta Lake。
from delta.tables import *
deltaTable = DeltaTable.forName(spark, "table_name")
deltaTable.optimize().where("date='2021-11-18'").executeCompaction()
Scala
Scala DeltaTable API 特定于 Delta Lake。
import io.delta.tables._
val deltaTable = DeltaTable.forName(spark, "table_name")
deltaTable.optimize().where("date='2021-11-18'").executeCompaction()
请考虑以下有关装箱问题的信息:
- 装箱优化具有幂等性,这意味着如果在同一数据集上运行两次,第二次运行不起作用。
- 装箱算法旨在生成在存储大小上均衡的数据文件,但并不一定要求每个文件中的元组数量均衡。 但是,这两个度量值通常相关。
对 Delta Lake 表的读取操作采用快照隔离,这意味着当 OPTIMIZE 从事务日志中删除不必要的文件时,读取操作不会被中断。 由于 OPTIMIZE 不会对表中的数据做任何更改,因此在 OPTIMIZE 之前和之后进行读取的结果是相同的。 对作为流式源的表执行 OPTIMIZE 不会影响任何当前或未来以该表为源的流。
OPTIMIZE 返回所删除文件的文件统计信息(最小值、最大值、总计等)和操作添加的文件。 优化统计信息还包含 Z 排序统计信息、批处理数和已优化分区数。
你还可以使用自动压缩来自动压缩小文件。 请参阅 自动压缩。
建议运行的频率 OPTIMIZE
对 Unity Catalog 托管表启用预测优化,以确保 OPTIMIZE 在经济高效时自动运行。
选择要运行 OPTIMIZE的频率时,性能与成本之间存在权衡。 为了提高最终用户查询性能,请更频繁地运行 OPTIMIZE。 由于资源使用量增加,这将产生更高的成本。 若要优化成本,请减少运行频率。
Databricks 建议从每天运行一次 OPTIMIZE 开始,然后调整频率以平衡成本和性能权衡。
适用于 OPTIMIZE 的推荐实例类型
这两个操作都是执行大量 Parquet 解码和编码的 CPU 密集型操作。
Databricks 建议使用计算优化实例类型。
OPTIMIZE 也受益于外接 SSD。