最佳實踐:Delta Lake

本文描述了使用Delta Lake時的最佳實踐。

提供數據位置提示

如果您希望一個列經常用於查詢謂詞,並且該列具有高基數性(即有大量不同的值),則使用z值通過.Delta Lake根據列值自動布局文件中的數據,並在查詢時使用布局信息跳過不相關的數據。

有關詳細信息,請參見z值(多維聚簇)

選擇正確的分區列

可以按列對Delta表進行分區。最常用的分區列為日期.遵循以下兩條經驗法則來決定用哪一列進行分區:

  • 如果一個列的基數非常高,不要使用該列進行分區。例如,如果按列劃分用戶標識如果有1M個不同的用戶id,那麼這是一個糟糕的分區策略。

  • 每個分區中的數據量:如果希望該分區中的數據至少為1 GB,則可以按列進行分區。

緊湊的文件

如果您不斷地向Delta表寫入數據,那麼隨著時間的推移,它將積累大量的文件,特別是當您以小批量的方式添加數據時。這可能會對表讀取的效率產生不利影響,還可能影響文件係統的性能。理想情況下,應該定期將大量的小文件重寫為少量的大文件。這就是所謂的壓縮。

可以將表格壓縮成優化命令。

替換表的內容或模式

有時您可能想要替換一個Delta表。例如:

  • 發現表中的數據不正確,希望替換內容。

  • 您希望重寫整個表以進行不兼容的模式更改(例如更改列類型)。

雖然您可以刪除Delta表的整個目錄,並在相同的路徑上創建一個新表,但是不推薦因為:

  • 刪除目錄效率不高。一個包含非常大文件的目錄可能需要數小時甚至數天才能刪除。

  • 刪除文件中的所有內容都將丟失;如果刪除了錯誤的表,則很難恢複。

  • 目錄刪除不是原子的。在刪除表時,讀取表的並發查詢可能失敗或隻能看到部分表。

  • 在S3上,您可能會遇到潛在的一致性問題,這隻是最終的一致性。

如果不需要更改表模式,則可以更改刪除數據並插入新數據,或者更新該表用於修複不正確的值。

如果要更改表模式,可以以原子的方式替換整個表。例如:

dataframe格式“δ”模式“覆蓋”選項“overwriteSchema”“真正的”partitionBy<你的-分區->saveAsTable“<表>”#管理表dataframe格式“δ”模式“覆蓋”選項“overwriteSchema”“真正的”選項“路徑”“< your-table-path >”partitionBy<你的-分區->saveAsTable“<表>”#外部表
取代表格<你的-表格>使用δ分區通過<你的-分區->作為選擇...——管理表取代表格<你的-表格>使用δ分區通過<你的-分區->位置“< your-table-path >”作為選擇...——外部表
dataframe格式“δ”模式“覆蓋”選項“overwriteSchema”“真正的”partitionBy<你的-分區->saveAsTable“<表>”/ /管理表dataframe格式“δ”模式“覆蓋”選項“overwriteSchema”“真正的”選項“路徑”“< your-table-path >”partitionBy<你的-分區->saveAsTable“<表>”/ /外部表

這種方法有很多好處:

  • 重寫表要快得多,因為它不需要遞歸地列出目錄或刪除任何文件。

  • 該表的舊版本仍然存在。如果您刪除了錯誤的表,您可以使用時間旅行

  • 這是一個原子操作。在刪除表時,並發查詢仍然可以讀取表。

  • 由於Delta Lake ACID事務保證,如果覆蓋表失敗,表將處於以前的狀態。

  • 在S3上您不會遇到任何一致性問題,因為您不刪除文件。

此外,如果您想刪除舊文件,以節省覆蓋表後的存儲成本,您可以使用真空刪除它們。它針對文件刪除進行了優化,通常比刪除整個目錄更快。

火花緩存

Databricks不建議您使用火花緩存原因如下:

  • 您丟失了任何可能來自添加在緩存之上的附加過濾器的數據跳過DataFrame

  • 如果使用不同的標識符訪問表,則緩存的數據可能不會更新spark.table (x) .cache ()然後寫入表使用spark.write.save(/一些/路徑)