本节介绍Delta使用过程中遇到的一些常见问题以及解决方法。

为什么建表失败?

Delta建表需要制定LOCATION,这种表在Spark中为外表。建表时,如果目标目录不存在,即创建一张全新的表,理论上不会出现这种情况。如果LOCATION已经存在,那么基于此LOCATION建表应当确保,建表语句的Schema与LOCATION内Delta log中定义的Schema相同。

流式写入Delta时产生了很多的小文件怎么办?

用Spark Streaming写数据到Delta,本质上是执行一系列的mini batch,一个batch会产生一个或者多个文件。由于batch size通常较小,因此Spark Streaming连续运行会产生相当数量的小文件。解决方法有两种:
  • 如果实时性要求不高,建议增大mini batch的trigger size。
  • 定期运行Optimize,对表进行合并小文件的操作。

Optimize执行时间很长是什么原因?

如果长时间没有进行Optimize操作,Delta内可能会累积相当数量的小文件,此时运行Optimize可能执行时间会比较长。因此建议设置定时任务来定期触发Optimize动作。

为什么Optimize失败了?应该如何处理?

Optimize会有删除历史数据和写新数据的动作。由于Delta采用的乐观锁机制,写事务在提交的时候,其中一个写事务会失败。尤其是一个流式作业在不断地更新Delta内的数据(例如:CDC场景),此时Optimize失败的概率会更大(注意:如果流式作业仅仅是新增数据而不涉及删除或者更新,Optimize不会失败)。建议用户对表进行基于时间的分区,每当一个分区完成,对该分区进行 Optimize操作。

执行了Optimize,为什么还有很多小文件?

Optimize是合并小文件,但是被合并的小文件不会被立即删除。因为Delta有访问历史的功能,因此如果要访问合并之前的历史版本,这些小文件会被用到。如果要删除这些小文件,请使用Vacuum命令。

执行了Vacuum,为什么还有很多小文件?

Vacuum动作是清理已经合并过的且已经超出了安全期的小文件。默认安全期为7天。如果小文件没有被合并过,或者合并过的小文件尚在安全期之内,Vacuum不会将之删除。

如果想删除最近产生的小文件(这些小文件已经被合并),应该如何处理?

不建议删除时间过近的小文件,因为Delta的历史访问功能可能会用到这些小文件。如果确实要这么做,有两种做法:
  • 关闭安全期检查:spark.databricks.delta.retentionDurationCheck.enabled=false,这个设置可以在启动spark任务时作为参数传入。
  • 修改全局的安全期为一个较小的值:例如在spark-defaults.conf 中设置spark.databricks.delta.properties.defaults.deletedFileRetentionDuration interval 1 hour

执行了Vacuum,为什么还有很多的Delta log文件?

Vacuum动作是合并数据文件,并非合并Delta log文件。Delta log文件的合并和清理Delta 自动做的,每经历10个提交,会自动触发一次Delta log的合并,合并之后同时检查超出安全期的log文件,如果超出,则删除。默认Delta log的安全期为30天。

有没有自动触发Optimize/Vacuum的机制?

Delta仅仅是一个库,而非运行时,因此尚没有自动化的机制,但可以设置定时任务定期来触发Optimize/Vacuum的机制。