HDFS非常容易存儲(chǔ)大數(shù)據(jù)文件,如果Hive中存在過多的小文件會(huì)給namecode帶來巨大的性能壓力。同時(shí)小文件過多會(huì)影響JOB的執(zhí)行烟勋,hadoop會(huì)將一個(gè)job轉(zhuǎn)換成多個(gè)task障癌,即使對(duì)于每個(gè)小文件也需要一個(gè)task去單獨(dú)處理,task作為一個(gè)獨(dú)立的jvm實(shí)例蹦玫,其開啟和停止的開銷可能會(huì)大大超過實(shí)際的任務(wù)處理時(shí)間。
同時(shí)我們知道hive輸出最終是mr的輸出,即reducer(或mapper)的輸出钳垮,有多少個(gè)reducer(mapper)輸出就會(huì)生成多少個(gè)輸出文件惑淳,根據(jù)shuffle/sort的原理,每個(gè)文件按照某個(gè)值進(jìn)行shuffle后的結(jié)果饺窿。
為了防止生成過多小文件歧焦,hive可以通過配置參數(shù)在mr過程中合并小文件。而且在執(zhí)行sql之前將小文件都進(jìn)行Merge肚医,也會(huì)提高程序的性能绢馍。我們可以從兩個(gè)方面進(jìn)行優(yōu)化,其一是map執(zhí)行之前將小文件進(jìn)行合并會(huì)提高性能肠套,其二是輸出的時(shí)候進(jìn)行合并壓縮舰涌,減少IO壓力。
1你稚、小文件帶來的問題
HDFS的文件元信息瓷耙,包括位置、大小刁赖、分塊信息等搁痛,都是保存在NameNode的內(nèi)存中的。每個(gè)對(duì)象大約占用150個(gè)字節(jié)宇弛,因此一千萬個(gè)文件及分塊就會(huì)占用約3G的內(nèi)存空間鸡典,一旦接近這個(gè)量級(jí),NameNode的性能就會(huì)開始下降了枪芒。此外彻况,HDFS讀寫小文件時(shí)也會(huì)更加耗時(shí),因?yàn)槊看味夹枰獜腘ameNode獲取元信息舅踪,并與對(duì)應(yīng)的DataNode建立連接纽甘。對(duì)于MapReduce程序來說,小文件還會(huì)增加Mapper的個(gè)數(shù)硫朦,每個(gè)腳本只處理很少的數(shù)據(jù)贷腕,浪費(fèi)了大量的調(diào)度時(shí)間。當(dāng)然咬展,這個(gè)問題可以通過使用CombinedInputFile和JVM重用來解決泽裳。
1.元數(shù)據(jù)信息增加給namenode節(jié)點(diǎn)造成壓力
2.讀寫小文件時(shí),獲取元數(shù)據(jù)信息更加耗時(shí)
3.mapper個(gè)數(shù)增加破婆,浪費(fèi)調(diào)度時(shí)間
2涮总、Hive小文件產(chǎn)生的原因
匯總后的數(shù)據(jù)量通常比源數(shù)據(jù)要少得多。而為了提升運(yùn)算速度祷舀,我們會(huì)增加Reducer的數(shù)量瀑梗,Hive本身也會(huì)做類似優(yōu)化——Reducer數(shù)量等于源數(shù)據(jù)的量除以hive.exec.reducers.bytes.per.reducer所配置的量(默認(rèn)1G)烹笔。Reducer數(shù)量的增加也即意味著結(jié)果文件的增加,從而產(chǎn)生小文件的問題抛丽。
3谤职、合并小文件
輸入合并。即在Map前合并小文件
輸出合并亿鲜。即在輸出結(jié)果的時(shí)候合并小文件
- 輸入合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
//執(zhí)行Map前進(jìn)行小文件合并
set mapred.max.split.size=256000000;
//每個(gè)Map最大輸入大小
set mapred.min.split.size.per.node=100000000;
//一個(gè)節(jié)點(diǎn)上split的至少的大小
set mapred.min.split.size.per.rack=100000000;
//一個(gè)交換機(jī)下split的至少的大小
- 輸出合并
set hive.merge.mapfiles = true
//在Map-only的任務(wù)結(jié)束時(shí)合并小文件
set hive.merge.tezfiles=true;
set hive.merge.mapredfiles = true
//在Map-Reduce的任務(wù)結(jié)束時(shí)合并小文件
set hive.merge.size.per.task = 256*1000*1000
//合并文件的大小
set hive.merge.smallfiles.avgsize=16000000
//當(dāng)輸出文件的平均大小小于該值時(shí)允蜈,啟動(dòng)一個(gè)獨(dú)立的map-reduce任務(wù)進(jìn)行文件merge
【參考】
https://blog.csdn.net/djd1234567/article/details/51581201