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://協議來指定路徑。
相關文章
- Hive表小檔案合併方法總結Hive
- iceberg合併小檔案衝突測試
- Spark優化之小檔案是否需要合併?Spark優化
- windows合併檔案Windows
- 合併iso檔案
- HDFS 07 - HDFS 效能調優之 合併小檔案
- git小技巧--提取/合併某分支的部分檔案Git
- Hive列合併與元素蒐集Hive
- Linux下合併檔案Linux
- git合併分支,如果選擇性的合併檔案?Git
- 徹底解決Hive小檔案問題Hive
- java快速分割及合併檔案Java
- 資料檔案合併與拆分
- shell 檔案合併 去重 分割
- 檔案切割以及合併筆記筆記
- Python之合併PDF檔案Python
- 超級檔案分割《合併》機(分割大檔案)
- Hbase-原理-region合併和hfile的合併(大合併、小合併)
- 辦公自動化:PDF檔案合併器,將多個PDF檔案進行合併
- Mac如何使用預覽應用合併PDF檔案 Mac合併PDF檔案教程詳解Mac
- 合併PDF檔案怎樣做?分享兩種PDF合併方法
- 多個 EXCEL 檔案如何合併成一個檔案Excel
- linux檔案合併、去重、拆分Linux
- Python合併多個csv檔案Python
- PHP 圖片的合併,微信小程式碼合併,文字合併PHP微信小程式
- 多個excel檔案合併成一個excel表的方法 如何快速合併多個excel檔案Excel
- Centos檔案切割利器_split命令及cat命令合併檔案CentOS
- 一款免費使用的PDF檔案批次合併工具,可操作pdf檔案順序,按順序合併pdf檔案。
- 一款免費使用的PDF檔案批量合併工具,可操作pdf檔案順序,按順序合併pdf檔案。
- PDF多檔案合併怎麼完成?PDF合併的簡單方法分享
- hive檔案數限制Hive
- Git 合併指定檔案或資料夾Git
- Linux大檔案的切割與合併Linux
- Android合併檔案的3種方式Android
- linux下檔案分割與合併 (轉)Linux
- linux下檔案分割與合併(轉)Linux
- git合併單個檔案到其他分支Git
- Flink SQL FileSystem Connector 分割槽提交與自定義小檔案合併策略 SQL