最佳實踐: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(/一些/路徑)
.