乾貨!Apache Hudi如何智慧處理小檔案問題

leesf發表於2021-04-11

1. 引入

Apache Hudi是一個流行的開源的資料湖框架,Hudi提供的一個非常重要的特性是自動管理檔案大小,而不用使用者干預。大量的小檔案將會導致很差的查詢分析效能,因為查詢引擎執行查詢時需要進行太多次檔案的開啟/讀取/關閉。在流式場景中不斷攝取資料,如果不進行處理,會產生很多小檔案。

2. 寫入時 vs 寫入後

一種常見的處理方法先寫入很多小檔案,然後再合併成大檔案以解決由小檔案引起的系統擴充套件性問題,但由於暴露太多小檔案可能導致不能保證查詢的SLA。實際上對於Hudi表,通過Hudi提供的Clustering功能可以非常輕鬆的做到這一點,更多細節可參考之前一篇文章查詢時間降低60%!Apache Hudi資料佈局黑科技瞭解下

本篇文章將介紹Hudi的檔案大小優化策略,即在寫入時處理。Hudi會自管理檔案大小,避免向查詢引擎暴露小檔案,其中自動處理檔案大小起很大作用。

在進行insert/upsert操作時,Hudi可以將檔案大小維護在一個指定檔案大小(注意:bulk_insert操作暫無此特性,其主要用於替換spark.write.parquet方式將資料快速寫入Hudi)。

3. 配置

我們使用COPY_ON_WRITE表來演示Hudi如何自動處理檔案大小特性。

關鍵配置項如下:

例如如果你第一個配置值設定為120MB,第二個配置值設定為100MB,則任何大小小於100MB的檔案都將被視為一個小檔案,如果要關閉此功能,可將hoodie.parquet.small.file.limit配置值設定為0。

4. 示例

假設一個指定分割槽下資料檔案佈局如下

假設配置的hoodie.parquet.max.file.size為120MB,hoodie.parquet.small.file.limit為100MB。File_1大小為40MB,File_2大小為80MB,File_3是90MB,File_4是130MB,File_5是105MB,當有新寫入時其流程如下:

步驟一:將更新分配到指定檔案,這一步將查詢索引來找到相應的檔案,假設更新會增加檔案的大小,會導致檔案變大。當更新減小檔案大小時(例如使許多欄位無效),則隨後的寫入將檔案將越來越小。

步驟二:根據hoodie.parquet.small.file.limit決定每個分割槽下的小檔案,我們的示例中該配置為100MB,所以小檔案為File_1、File_2和File_3;

步驟三:確定小檔案後,新插入的記錄將分配給小檔案以便使其達到120MB,File_1將會插入80MB大小的記錄數,File_2將會插入40MB大小的記錄數,File_3將插入30MB大小的記錄數。

步驟四:當所有小檔案都分配完了對應插入記錄數後,如果還有剩餘未分配的插入記錄,這些記錄將分配給新建立的FileGroup/資料檔案。資料檔案中的記錄數由hoodie.copyonwrite.insert.split.size(或者由之前的寫入自動推算每條記錄大小,然後根據配置的最大檔案大小計算出來可以插入的記錄數)決定,假設最後得到的該值為120K(每條記錄大小1K),如果還剩餘300K的記錄數,將會建立3個新檔案(File_6,File_7,File_8),File_6和File_7都會分配120K的記錄數,File_8會分配60K的記錄數,共計60MB,後面再寫入時,File_8會被認為小檔案,可以插入更多資料。

Hudi利用諸如自定義分割槽之類的機制來優化記錄分配到不同檔案的能力,從而執行上述演算法。在這輪寫入完成之後,除File_8以外的所有檔案均已調整為最佳大小,每次寫入都會遵循此過程,以確保Hudi表中沒有小檔案。

5. 總結

本文介紹了Apache Hudi如何智慧地管理小檔案問題,即在寫入時找出小檔案並分配指定大小的記錄數來規避小檔案問題,基於該設計,使用者再也不用擔心Apache Hudi資料湖中的小檔案問題了。

相關文章