您好,登錄后才能下訂單哦!
這篇文章將為大家詳細講解有關如何解決hive小文件過多問題,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。
hive 中的小文件肯定是向 hive 表中導入數據時產生,所以先看下向 hive 中導入數據的幾種方式
直接向表中插入數據
insert into table A values (1,'zhangsan',88),(2,'lisi',61);
這種方式每次插入時都會產生一個文件,多次插入少量數據就會出現多個小文件,但是這種方式生產環境很少使用,可以說基本沒有使用的
通過load方式加載數據
load data local inpath '/export/score.csv' overwrite into table A -- 導入文件load data local inpath '/export/score' overwrite into table A -- 導入文件夾
使用 load 方式可以導入文件或文件夾,當導入一個文件時,hive表就有一個文件,當導入文件夾時,hive表的文件數量為文件夾下所有文件的數量
通過查詢方式加載數據
insert overwrite table A select s_id,c_name,s_score from B;
這種方式是生產環境中常用的,也是最容易產生小文件的方式
insert 導入數據時會啟動 MR 任務,MR中 reduce 有多少個就輸出多少個文件
所以, 文件數量=ReduceTask數量*分區數
也有很多簡單任務沒有reduce,只有map階段,則
文件數量=MapTask數量*分區數
每執行一次 insert 時hive中至少產生一個文件,因為 insert 導入時至少會有一個MapTask。
像有的業務需要每10分鐘就要把數據同步到 hive 中,這樣產生的文件就會很多。
首先對底層存儲HDFS來說,HDFS本身就不適合存儲大量小文件,小文件過多會導致namenode元數據特別大, 占用太多內存,嚴重影響HDFS的性能
對 hive 來說,在進行查詢時,每個小文件都會當成一個塊,啟動一個Map任務來完成,而一個Map任務啟動和初始化的時間遠遠大于邏輯處理的時間,就會造成很大的資源浪費。而且,同時可執行的Map數量是受限的。
使用方法:
#對于非分區表alter table A concatenate;#對于分區表alter table B partition(day=20201224) concatenate;
舉例:
#向 A 表中插入數據hive (default)> insert into table A values (1,'aa',67),(2,'bb',87); hive (default)> insert into table A values (3,'cc',67),(4,'dd',87); hive (default)> insert into table A values (5,'ee',67),(6,'ff',87);#執行以上三條語句,則A表下就會有三個小文件,在hive命令行執行如下語句#查看A表下文件數量hive (default)> dfs -ls /user/hive/warehouse/A; Found 3 items -rwxr-xr-x 3 root supergroup 378 2020-12-24 14:46 /user/hive/warehouse/A/000000_0 -rwxr-xr-x 3 root supergroup 378 2020-12-24 14:47 /user/hive/warehouse/A/000000_0_copy_1 -rwxr-xr-x 3 root supergroup 378 2020-12-24 14:48 /user/hive/warehouse/A/000000_0_copy_2#可以看到有三個小文件,然后使用 concatenate 進行合并hive (default)> alter table A concatenate;#再次查看A表下文件數量hive (default)> dfs -ls /user/hive/warehouse/A; Found 1 items -rwxr-xr-x 3 root supergroup 778 2020-12-24 14:59 /user/hive/warehouse/A/000000_0#已合并成一個文件
注意:
1、concatenate 命令只支持 RCFILE 和 ORC 文件類型。
2、使用concatenate命令合并小文件時不能指定合并后的文件數量,但可以多次執行該命令。
3、當多次使用concatenate后文件數量不在變化,這個跟參數 mapreduce.input.fileinputformat.split.minsize=256mb 的設置有關,可設定每個文件的最小size。
設置map輸入合并小文件的相關參數:
#執行Map前進行小文件合并#CombineHiveInputFormat底層是 Hadoop的 CombineFileInputFormat 方法#此方法是在mapper中將多個文件合成一個split作為輸入set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; -- 默認#每個Map最大輸入大小(這個值決定了合并后文件的數量)set mapred.max.split.size=256000000; -- 256M#一個節點上split的至少的大小(這個值決定了多個DataNode上的文件是否需要合并)set mapred.min.split.size.per.node=100000000; -- 100M#一個交換機下split的至少的大小(這個值決定了多個交換機上的文件是否需要合并)set mapred.min.split.size.per.rack=100000000; -- 100M
設置map輸出和reduce輸出進行合并的相關參數:
#設置map端輸出進行合并,默認為trueset hive.merge.mapfiles = true;#設置reduce端輸出進行合并,默認為falseset hive.merge.mapredfiles = true;#設置合并文件的大小set hive.merge.size.per.task = 256*1000*1000; -- 256M#當輸出文件的平均大小小于該值時,啟動一個獨立的MapReduce任務進行文件mergeset hive.merge.smallfiles.avgsize=16000000; -- 16M
啟用壓縮
# hive的查詢結果輸出是否進行壓縮set hive.exec.compress.output=true;# MapReduce Job的結果輸出是否使用壓縮set mapreduce.output.fileoutputformat.compress=true;
#reduce 的個數決定了輸出的文件的個數,所以可以調整reduce的個數控制hive表的文件數量,#hive中的分區函數 distribute by 正好是控制MR中partition分區的,#然后通過設置reduce的數量,結合分區函數讓數據均衡的進入每個reduce即可。#設置reduce的數量有兩種方式,第一種是直接設置reduce個數set mapreduce.job.reduces=10;#第二種是設置每個reduce的大小,Hive會根據數據總大小猜測確定一個reduce個數set hive.exec.reducers.bytes.per.reducer=5120000000; -- 默認是1G,設置為5G#執行以下語句,將數據均衡的分配到reduce中set mapreduce.job.reduces=10;insert overwrite table A partition(dt)select * from Bdistribute by rand(); 解釋:如設置reduce數量為10,則使用 rand(), 隨機生成一個數 x % 10 , 這樣數據就會隨機進入 reduce 中,防止出現有的文件過大或過小
Hadoop Archive簡稱HAR,是一個高效地將小文件放入HDFS塊中的文件存檔工具,它能夠將多個小文件打包成一個HAR文件,這樣在減少namenode內存使用的同時,仍然允許對文件進行透明的訪問
#用來控制歸檔是否可用set hive.archive.enabled=true;#通知Hive在創建歸檔時是否可以設置父目錄set hive.archive.har.parentdir.settable=true;#控制需要歸檔文件的大小set har.partfile.size=1099511627776;#使用以下命令進行歸檔ALTER TABLE A ARCHIVE PARTITION(dt='2020-12-24', hr='12');#對已歸檔的分區恢復為原文件ALTER TABLE A UNARCHIVE PARTITION(dt='2020-12-24', hr='12');
注意:
歸檔的分區可以查看不能 insert overwrite,必須先 unarchive
如果是新集群,沒有歷史遺留問題的話,建議hive使用 orc 文件格式,以及啟用 lzo 壓縮。
這樣小文件過多可以使用hive自帶命令 concatenate 快速合并。
關于如何解決hive小文件過多問題就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。