溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何解決hive小文件過多問題

發(fā)布時間:2021-12-06 17:01:56 來源:億速云 閱讀:158 作者:柒染 欄目:大數(shù)據(jù)

這篇文章將為大家詳細(xì)講解有關(guān)如何解決hive小文件過多問題,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關(guān)知識有一定的了解。

小文件產(chǎn)生原因

hive 中的小文件肯定是向 hive 表中導(dǎo)入數(shù)據(jù)時產(chǎn)生,所以先看下向 hive 中導(dǎo)入數(shù)據(jù)的幾種方式

  1. 直接向表中插入數(shù)據(jù)

insert into table A values (1,'zhangsan',88),(2,'lisi',61);

這種方式每次插入時都會產(chǎn)生一個文件,多次插入少量數(shù)據(jù)就會出現(xiàn)多個小文件,但是這種方式生產(chǎn)環(huán)境很少使用,可以說基本沒有使用的

  1. 通過load方式加載數(shù)據(jù)

load data local inpath '/export/score.csv' overwrite into table A  -- 導(dǎo)入文件load data local inpath '/export/score' overwrite into table A   -- 導(dǎo)入文件夾

使用 load 方式可以導(dǎo)入文件或文件夾,當(dāng)導(dǎo)入一個文件時,hive表就有一個文件,當(dāng)導(dǎo)入文件夾時,hive表的文件數(shù)量為文件夾下所有文件的數(shù)量

  1. 通過查詢方式加載數(shù)據(jù)

insert overwrite table A  select s_id,c_name,s_score from B;

這種方式是生產(chǎn)環(huán)境中常用的,也是最容易產(chǎn)生小文件的方式

insert 導(dǎo)入數(shù)據(jù)時會啟動 MR 任務(wù),MR中 reduce 有多少個就輸出多少個文件

所以, 文件數(shù)量=ReduceTask數(shù)量*分區(qū)數(shù)

也有很多簡單任務(wù)沒有reduce,只有map階段,則

文件數(shù)量=MapTask數(shù)量*分區(qū)數(shù)

每執(zhí)行一次 insert 時hive中至少產(chǎn)生一個文件,因?yàn)?insert 導(dǎo)入時至少會有一個MapTask。
像有的業(yè)務(wù)需要每10分鐘就要把數(shù)據(jù)同步到 hive 中,這樣產(chǎn)生的文件就會很多。

小文件過多產(chǎn)生的影響

  1. 首先對底層存儲HDFS來說,HDFS本身就不適合存儲大量小文件,小文件過多會導(dǎo)致namenode元數(shù)據(jù)特別大, 占用太多內(nèi)存,嚴(yán)重影響HDFS的性能

  2. 對 hive 來說,在進(jìn)行查詢時,每個小文件都會當(dāng)成一個塊,啟動一個Map任務(wù)來完成,而一個Map任務(wù)啟動和初始化的時間遠(yuǎn)遠(yuǎn)大于邏輯處理的時間,就會造成很大的資源浪費(fèi)。而且,同時可執(zhí)行的Map數(shù)量是受限的。

怎么解決小文件過多

1. 使用 hive 自帶的 concatenate 命令,自動合并小文件

使用方法:

#對于非分區(qū)表alter table A concatenate;#對于分區(qū)表alter table B partition(day=20201224) concatenate;

舉例:

#向 A 表中插入數(shù)據(jù)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);#執(zhí)行以上三條語句,則A表下就會有三個小文件,在hive命令行執(zhí)行如下語句#查看A表下文件數(shù)量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 進(jìn)行合并hive (default)> alter table A concatenate;#再次查看A表下文件數(shù)量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命令合并小文件時不能指定合并后的文件數(shù)量,但可以多次執(zhí)行該命令。
3、當(dāng)多次使用concatenate后文件數(shù)量不在變化,這個跟參數(shù) mapreduce.input.fileinputformat.split.minsize=256mb 的設(shè)置有關(guān),可設(shè)定每個文件的最小size。

2. 調(diào)整參數(shù)減少M(fèi)ap數(shù)量
  • 設(shè)置map輸入合并小文件的相關(guān)參數(shù)

#執(zhí)行Map前進(jìn)行小文件合并#CombineHiveInputFormat底層是 Hadoop的 CombineFileInputFormat 方法#此方法是在mapper中將多個文件合成一個split作為輸入set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; -- 默認(rèn)#每個Map最大輸入大小(這個值決定了合并后文件的數(shù)量)set mapred.max.split.size=256000000;   -- 256M#一個節(jié)點(diǎn)上split的至少的大小(這個值決定了多個DataNode上的文件是否需要合并)set mapred.min.split.size.per.node=100000000;  -- 100M#一個交換機(jī)下split的至少的大小(這個值決定了多個交換機(jī)上的文件是否需要合并)set mapred.min.split.size.per.rack=100000000;  -- 100M
  • 設(shè)置map輸出和reduce輸出進(jìn)行合并的相關(guān)參數(shù):

#設(shè)置map端輸出進(jìn)行合并,默認(rèn)為trueset hive.merge.mapfiles = true;#設(shè)置reduce端輸出進(jìn)行合并,默認(rèn)為falseset hive.merge.mapredfiles = true;#設(shè)置合并文件的大小set hive.merge.size.per.task = 256*1000*1000;   -- 256M#當(dāng)輸出文件的平均大小小于該值時,啟動一個獨(dú)立的MapReduce任務(wù)進(jìn)行文件mergeset hive.merge.smallfiles.avgsize=16000000;   -- 16M
  • 啟用壓縮

# hive的查詢結(jié)果輸出是否進(jìn)行壓縮set hive.exec.compress.output=true;# MapReduce Job的結(jié)果輸出是否使用壓縮set mapreduce.output.fileoutputformat.compress=true;
3. 減少Reduce的數(shù)量
#reduce 的個數(shù)決定了輸出的文件的個數(shù),所以可以調(diào)整reduce的個數(shù)控制hive表的文件數(shù)量,#hive中的分區(qū)函數(shù) distribute by 正好是控制MR中partition分區(qū)的,#然后通過設(shè)置reduce的數(shù)量,結(jié)合分區(qū)函數(shù)讓數(shù)據(jù)均衡的進(jìn)入每個reduce即可。#設(shè)置reduce的數(shù)量有兩種方式,第一種是直接設(shè)置reduce個數(shù)set mapreduce.job.reduces=10;#第二種是設(shè)置每個reduce的大小,Hive會根據(jù)數(shù)據(jù)總大小猜測確定一個reduce個數(shù)set hive.exec.reducers.bytes.per.reducer=5120000000; -- 默認(rèn)是1G,設(shè)置為5G#執(zhí)行以下語句,將數(shù)據(jù)均衡的分配到reduce中set mapreduce.job.reduces=10;insert overwrite table A partition(dt)select * from Bdistribute by rand();

解釋:如設(shè)置reduce數(shù)量為10,則使用 rand(), 隨機(jī)生成一個數(shù) x % 10 ,
這樣數(shù)據(jù)就會隨機(jī)進(jìn)入 reduce 中,防止出現(xiàn)有的文件過大或過小
4. 使用hadoop的archive將小文件歸檔

Hadoop Archive簡稱HAR,是一個高效地將小文件放入HDFS塊中的文件存檔工具,它能夠?qū)⒍鄠€小文件打包成一個HAR文件,這樣在減少namenode內(nèi)存使用的同時,仍然允許對文件進(jìn)行透明的訪問

#用來控制歸檔是否可用set hive.archive.enabled=true;#通知Hive在創(chuàng)建歸檔時是否可以設(shè)置父目錄set hive.archive.har.parentdir.settable=true;#控制需要?dú)w檔文件的大小set har.partfile.size=1099511627776;#使用以下命令進(jìn)行歸檔ALTER TABLE A ARCHIVE PARTITION(dt='2020-12-24', hr='12');#對已歸檔的分區(qū)恢復(fù)為原文件ALTER TABLE A UNARCHIVE PARTITION(dt='2020-12-24', hr='12');

注意:
歸檔的分區(qū)可以查看不能 insert overwrite,必須先 unarchive

最后

如果是新集群,沒有歷史遺留問題的話,建議hive使用 orc 文件格式,以及啟用 lzo 壓縮。
這樣小文件過多可以使用hive自帶命令 concatenate 快速合并。

關(guān)于如何解決hive小文件過多問題就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,可以學(xué)到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI