A. Spark 處理小文件
不論是Hive還是Spark SQL在使用過程中都可能會遇到小文件過多的問題。小文件過多最直接的表現是任務執行時間長,查看Spark log會發現大量的數據移動的日誌。我們可以查看log中展現的日誌信息,去對應的路徑下查看文件的大小和個數。租敬稿
通過上述命令可以查看文件的個數以及大小。count查看出的文件大小單位是B,需要轉換為MB。
在spark官方的推薦文檔中,parquet格式的文件推薦大小是128MB,小於該大小的均可以稱之為小文件,在實際的工作,往往小文件的大小僅僅為幾KB,表現為,可能文件大小為幾百MB,但是文件個數可能到達了幾十萬個。一般來說,我們可以通過簡單相除獲得文件的平均大小,如果文件數目不多,我們也可以通過下述命令獲得每個文件的大小。
1.任務執行時間長
2.真實的文件大小獨佔一個數據存儲塊,存放到DataNode節點中。同時 DataNode一般默認存三份副本,以保障數據安全。同時該文件所存放的位置也寫入到NameNode的內存中,如果有Secondary NameNode高可用節點,也可同時復制一份過去。NameNode的內存數據將會存放到硬碟中,如果HDFS發生重弊孝啟,將產生較長時間的元數據從硬碟讀到內存的過程。
3.不論在Hive還是在Spark中,每一個存儲塊都對應一個Map程序,一個Map呈現就需要一個JVM,啟動一個JVM去讀取或者寫小文件是吃力不討好的行為。在實際的生產中,為了更好的管理集群資源,一般會要求程序執行時限制Executor數量和每個Executor的核心數量,需要頻繁創建Executor來讀取寫入。
5.影響磁碟定址時間
小文件合並,本質上就是通過某種操作,將一系列小文件合並成大文件。我們知道,以MapRece為代表的大數據系統,都習慣用K-V鍵值對的形式來處理文件,最後文件落盤,也是一個rece對應一個輸出文件。所以直觀上,我們可以減少rece數量,達到減少文件數量的目的。
從Map到Rece需要一個Shuffle過程,所以我們將小文件合並理解為通過一個Shuffle,合並小文件成一個大文件。基於這樣的思想,我們的策略可以稿耐分為兩類:一類是原來的計算已經有Shuffle了,那麼我們可以認為控制輸出文件的數量;二類是強制觸發Shuffle,進行小文件合並。
1-設置參數 (一般用於Hive)
2-distribute by rand()
往動態分區插入數據時,在已經寫好的SQL末尾加上distribute by rand()
該運算元只是起到打散的效果,但是我們還要設置文件的大小,以免打散後仍然有小文件。
表示每個rece的大小,Hive可以數據總量,得到rece個數,假設hive認為會有10個rece,那麼,這里rand()則會為 x % 10
3-group by
我們知道,group by運算元會觸發Shuffle,因此只要我們設置好Shuffle時的文件個數就好,在Spark SQL中,我們可以設置partition個數,因為一個partition會對應一個文件。
上述的操作,會觸發shuffle,因此我們再設置partition個數。
則表示,shuffle後,只會產生10個partition.
4-repartition()
5-coalesce()
需要注意的是,4和5都是spark 2.4以及以後才會支持的。
B. Hive如何處理大量小文件
1.動態分區插入數據的時候,會產生大量的小文件,從而導致map數量的暴增
2.數據源本身就包含有大量的小文件
3.rece個數越多,生成的小文件也越多
1 從HIVE角度來看的話呢,小文件越多,map的個數也會越多,每一個map都會開啟一個JVM虛擬機,每個虛擬機都要創建任務,執行任務,這些流程都會造成大量的資源浪費,嚴重影響性能
2 在HDFS中,每個小文件約佔150byte,如果小文件過多則會佔用大量的內存。這樣namenode內存容量嚴重製約了集群的發展
4.1 使用Hadoop achieve把小文件進行歸檔
4.2 重建表,建表時減少rece的數量
4.3 通過參數調節,設洞閉置map/rece的數量
4.3.1設置兄悔map輸入合並小文件的相關納塵裂參數:
4.3.2 設置map輸出和rece輸出進行合並的相關參數: