本文匯總了DeltaLake使用時的常見問題。
為什么建表失敗?
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的機制。