當Hive的輸入由很多個小文件組成時,如果不涉及文件合並的話,那麼每個小文件都會啟動一個map task。
如果文件過小,以至於map任務啟動和初始化的時間大於邏輯處理的時間,會造成資源浪費,甚至發生OutOfMemoryError錯誤。
因此,當我們啟動一個任務時,如果發現輸入數據量小但任務數量多時,需要注意在Map前端進行輸入小文件合並操作。
同理,向一個表寫數據時,注意觀察reduce數量,注意輸出文件大小。
1、 Map輸入小文件合並
#每個Map處理的最大輸入文件大小(256MB)
set mapred.max.split.size=256000000;
#一個節點上split文件的最小值
set mapred.min.split.size.per.node=100000000;
#一個交換機下split文件的最小值
set mapred.min.split.size.per.rack=100000000;
#執行Map前進行小文件合並
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
在開啟了org.apache.hadoop.hive.ql.io.CombineHiveInputFormat 後,
一個data node節點上多個小文件會進行合並,合並文件數由mapred.max.split.size限制的大小決定。
mapred.min.split.size.per.node決定了多個data node上的文件是否需要合並
mapred.min.split.size.per.rack決定了多個交換機上的文件是否需要合並
2、輸出文件合並
#在Map-Only的任務結束時就會合並小文件
set hive.merge.mapfiles = true;
#在MapR-educe的任務結束時合並小文件
set hive.merge.mapredfiles = true;(默認為false)
#合並文件的大小
set hive.merge.size.per.task = 256*1000*1000;
#當輸出文件的平均大小小於該值時,啟動一個獨立的map-reduce任務進行文件merge
set hive.merge.smallfiles.avgsize=16000000 ;