hive小文件合並設置參數


Hive的后端存儲是HDFS,它對大文件的處理是非常高效的,如果合理配置文件系統的塊大小,NameNode可以支持很大的數據量。但是在數據倉庫中,越是上層的表其匯總程度就越高,數據量也就越小。而且這些表通常會按日期進行分區,隨着時間的推移,HDFS的文件數目就會逐漸增加。
 
小文件帶來的問題
 
關於這個問題的闡述可以讀一讀Cloudera的這篇文章。簡單來說,HDFS的文件元信息,包括位置、大小、分塊信息等,都是保存在NameNode的內存中的。每個對象大約占用150個字節,因此一千萬個文件及分塊就會占用約3G的內存空間,一旦接近這個量級,NameNode的性能就會開始下降了。
 
此外,HDFS讀寫小文件時也會更加耗時,因為每次都需要從NameNode獲取元信息,並與對應的DataNode建立連接。對於MapReduce程序來說,小文件還會增加Mapper的個數,每個腳本只處理很少的數據,浪費了大量的調度時間。當然,這個問題可以通過使用CombinedInputFile和JVM重用來解決。
 
Hive小文件產生的原因
 
前面已經提到,匯總后的數據量通常比源數據要少得多。而為了提升運算速度,我們會增加Reducer的數量,Hive本身也會做類似優化——Reducer數量等於源數據的量除以hive.exec.reducers.bytes.per.reducer所配置的量(默認1G)。Reducer數量的增加也即意味着結果文件的增加,從而產生小文件的問題。
解決小文件的問題可以從兩個方向入手:
1. 輸入合並。即在Map前合並小文件
2. 輸出合並。即在輸出結果的時候合並小文件
 
配置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; 
 
配置Hive結果合並
 
我們可以通過一些配置項來使Hive在執行結束后對結果文件進行合並:
 
hive.merge.mapfiles 在map-only job后合並文件,默認true
hive.merge.mapredfiles 在map-reduce job后合並文件,默認false
hive.merge.size.per.task 合並后每個文件的大小,默認256000000
hive.merge.smallfiles.avgsize 平均文件大小,是決定是否執行合並操作的閾值,默認16000000
 
Hive在對結果文件進行合並時會執行一個額外的map-only腳本,mapper的數量是文件總大小除以size.per.task參數所得的值,觸發合並的條件是:
根據查詢類型不同,相應的mapfiles/mapredfiles參數需要打開;
結果文件的平均大小需要大於avgsize參數的值。
示例:
 
-- map-red job,5個reducer,產生5個60K的文件。
create table dw_stage.zj_small as
select paid, count (*)
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
group by paid;
-- 執行額外的map-only job,一個mapper,產生一個300K的文件。
set hive.merge.mapredfiles= true;
create table dw_stage.zj_small as
select paid, count (*)
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
group by paid;
-- map-only job,45個mapper,產生45個25M左右的文件。
create table dw_stage.zj_small as
select *
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
and paid like '%baidu%' ;
-- 執行額外的map-only job,4個mapper,產生4個250M左右的文件。
set hive.merge.smallfiles.avgsize=100000000;
create table dw_stage.zj_small as
select *
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
and paid like '%baidu%' ;
 
壓縮文件的處理
對於輸出結果為壓縮文件形式存儲的情況,要解決小文件問題,如果在Map輸入前合並,對輸出的文件存儲格式並沒有限制。但是如果使用輸出合並,則必須配合SequenceFile來存儲,否則無法進行合並,以下是示例:
 
set mapred.output.compression. type=BLOCK;
set hive.exec.compress.output= true;
set mapred.output.compression.codec=org.apache.hadoop.io.compress.LzoCodec;
set hive.merge.smallfiles.avgsize=100000000;
drop table if exists dw_stage.zj_small;
create table dw_stage.zj_small
STORED AS SEQUENCEFILE
as select *
from dw_db.dw_soj_imp_dtl
where log_dt = '2014-04-14'
and paid like '%baidu%' ;
 
使用HAR歸檔文件
 
Hadoop的歸檔文件格式也是解決小文件問題的方式之一。而且Hive提供了原生支持:
 
set hive.archive.enabled= true;
set hive.archive.har.parentdir.settable= true;
set har.partfile.size=1099511627776;
ALTER TABLE srcpart ARCHIVE PARTITION(ds= '2008-04-08', hr= '12' );
ALTER TABLE srcpart UNARCHIVE PARTITION(ds= '2008-04-08', hr= '12' );
 
如果使用的不是分區表,則可創建成外部表,並使用har://協議來指定路徑。
 
來源:https://blog.csdn.net/yycdaizi/article/details/43341239


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM