問題背景:
公司集羣有個表, 執行一次insert overwrite table select * from table; 大概需要7000s.
源表是從pgsql抽上來的, 用了500個maptasks.
該表以月爲分區, 每個分區文件夾下面產生了大量的小文件, 有的都不到1M.
問題產生原因:
輸入表本身就有很多小文件, 插入的時候沒有限制reduce個數, 資源也沒有限制, 導致產生很多個ReduceTasks, 進而產生多個小文件.
解決方案:
1. 在Map輸入的時候, 把小文件合併.
-- 每個Map最大輸入大小,決定合併後的文件數
set mapred.max.split.size=256000000;
-- 一個節點上split的至少的大小 ,決定了多個data node上的文件是否需要合併
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;
2. 在Reduce輸出的時候, 把小文件合併.
-- 在map-only job後合併文件,默認true
set hive.merge.mapfiles = true;
-- 在map-reduce job後合併文件,默認false
set hive.merge.mapredfiles = true;
-- 合併後每個文件的大小,默認256000000
set hive.merge.size.per.task = 256000000;
-- 平均文件大小,是決定是否執行合併操作的閾值,默認16000000
set hive.merge.smallfiles.avgsize = 100000000;
參考文章:
https://blog.csdn.net/yycdaizi/article/details/43341239
http://shzhangji.com/cnblogs/2014/04/07/hive-small-files/