本文介绍优化表的一些使用示例。

Optimize

  • Scala
    import io.delta.tables._
    
    val deltaTable = DeltaTable.forPath(spark, "/tmp/delta_table")
    
    deltaTable.optimizeExpr("date < '2019-11-11'", Seq("date", "id"))                       // 使用 SQL 字符串
    
    import org.apache.spark.sql.functions._
    import spark.implicits._
    
    deltaTable.optimize(col("date < '2019-11-11'"), Seq(col("date"), col("id")))            // 使用 SQL 函数和隐式转换
  • SQL
    OPTIMIZE delta_table [WHERE t.date < '2019-11-11'] [ZORDER BY t.date,t.id];
    说明
    • deltaTable.optimize()也可以不指定参数,表示对全表进行优化。
    • ZORDER功能暂时不支持(Scala API 中的第二个参数以及SQL中的ZORDER BY子句)。

Vacuum

Vacuum用于清理历史文件。经过Optimize后,小文件会被合并为大文件,但是原有小文件不会被删除,因为Delta有访问历史的功能,当访问历史版本时,仍然需要读取这些小文件。如果这些文件涉及到的数据过时很久,而且这些小文件已经被合并过了(被标记为墓碑文件),那么可以用Vacuum命令将其物理删除。默认情况下,被标记为墓碑的文件只有经过一个安全期才能被删除,如果删除一个尚在安全期内的文件,将会抛出异常。

如果您要删除近期的,例如1天前的已经合并过的小文件,可通过以下两种方式:

  • 设置合理的安全期参数(推荐):spark.databricks.delta.properties.defaults.deletedFileRetentionDurationinterval 1 day, 2 weeks365 days等等。不支持MonthYear的设置。该参数为表的静态属性,无法通过命令行或者--conf设置。其设置方法为:
    1. spark-default.conf为配置为全局属性。
    2. 通过ALTER TABLE <tbl> SET PROPERTIES (key=value)更改此表属性。
  • 通过关闭安全期检查(不推荐):设置(通过命令行set或者使用--conf参数) set spark.databricks.delta.retentionDurationCheck.enabled = flase关闭后,即可删除近期合并过的小文件。
注意
  1. 强烈不建议关闭安全期检查。
  2. 不建议设置过小的安全期。过小的安全期设置可能导致正在读取某一历史版本的作业失败,甚至,如果安全期非常小,当前正在执行作业产生的临时文件也可能被清理掉从而导致作业失败。
  • Scala
    import io.delta.tables._
    
    val deltaTable = DeltaTable.forPath(spark, pathToTable)
    
    deltaTable.vacuum()        // 物理删除超出安全期的墓碑文件
    deltaTable.vacuum(100)     // 物理删除100小时前的墓碑文件
  • SQL
    VACUUM table_name [RETAIN num HOURS] [DRY RUN]
    说明
    • 通过RETAIN子句指定删除超出设置时间间隔的墓碑文件。RETAIN num HOURS的默认值为spark.databricks.delta.properties.defaults.deletedFileRetentionDuration指定的值。
    • 如果指定了DRY RUN,则被删除文件会被列出而不实际删除。