hive - 可优化的 10 个地方及详解
1.合理選擇排序
排序算法比較耗資源,應(yīng)根據(jù)業(yè)務(wù)需要選擇
- order by :全局排序,大數(shù)據(jù)集會(huì)消耗太過(guò)漫長(zhǎng)的時(shí)間
- sort by:局部排序,只能保證每個(gè)reducer的輸出數(shù)據(jù)都是有序的
- distribute by:分桶不排序,控制map的輸出在reducer中是如何劃分的,若需排序,則+sort by[字段]
- cluster by:分桶且排序
?
?
2.慎用笛卡爾積
與join關(guān)聯(lián)不同,笛卡爾積沒(méi)有關(guān)聯(lián)條件,轉(zhuǎn)換成mr程序的時(shí)候,所有數(shù)據(jù)都進(jìn)入一個(gè)reducetask中,性能極低。
左表:stu 右表:sco 右表:sco_copy
huang math 1 music 1 music 2
meng chinese 2 read 1 read 2
jun english 1
zheng math 2
fan it 1
若無(wú)法避免,則需要增加reducetask的個(gè)數(shù):
1、假設(shè)需要增加reducetask的個(gè)數(shù)為2,將右表復(fù)制一個(gè),形成兩個(gè)右表;
create table sco_copy as select * from sco;
2、為右表增加關(guān)聯(lián)鍵index,右表1的關(guān)聯(lián)鍵均等于1,右表2的關(guān)聯(lián)鍵均等于2;
3、為左表增加關(guān)聯(lián)鍵index,根據(jù)1、2、1、2...的順序添加,可防止數(shù)據(jù)傾斜;
將左表的大表分解成兩部分,分別對(duì)兩個(gè)一樣的右表進(jìn)行關(guān)聯(lián)鍵匹配,增加reducetask的并行度,提高效率。
?
?
3.合并小文件
小文件過(guò)多會(huì)導(dǎo)致maptask的個(gè)數(shù)過(guò)多,則導(dǎo)致container的啟動(dòng)和銷毀的次數(shù)過(guò)多,啟動(dòng)銷毀的時(shí)間遠(yuǎn)遠(yuǎn)大于程序運(yùn)行的時(shí)間。
(輸入合并)原始數(shù)據(jù)中的小文件過(guò)多,合并。
對(duì)應(yīng)參數(shù):
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的至少的大小
執(zhí)行Map前進(jìn)行小文件合并(常用)
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; ?
在開(kāi)啟了org.apache.hadoop.hive.ql.io.CombineHiveInputFormat后,一個(gè)data node節(jié)點(diǎn)上多個(gè)小文件會(huì)進(jìn)行合并,合并文件數(shù)由mapred.max.split.size限制的大小決定。
mapred.min.split.size.per.node決定了多個(gè)data node上的文件是否需要合并~
mapred.min.split.size.per.rack決定了多個(gè)交換機(jī)上的文件是否需要合并~
?
(輸出合并)當(dāng)hql中存在多個(gè)mr程序串聯(lián)的時(shí)候,上個(gè)mr程序的reducetask的個(gè)數(shù)為3,則會(huì)輸出3個(gè)文件,要合并后進(jìn)入下一個(gè)mr程序。
set?hive.merge.mapfiles = true #在Map-only的任務(wù)結(jié)束時(shí)合并小文件 set?hive.merge.mapredfiles?= true #在Map-Reduce的任務(wù)結(jié)束時(shí)合并小文件 set hive.merge.size.per.task = 256*1000*1000 #合并文件的大小
當(dāng)輸出文件的平均大小小于該值時(shí),啟動(dòng)一個(gè)獨(dú)立的map-reduce任務(wù)進(jìn)行文件merge
set?hive.merge.smallfiles.avgsize=16000000
?
?
4.合理設(shè)計(jì)maptask的個(gè)數(shù)(最好128M一個(gè))
個(gè)數(shù)過(guò)多,效率低主要是container的啟動(dòng)和銷毀時(shí)間耽誤的;
若是小文件過(guò)多導(dǎo)致的,則執(zhí)行上面的合并小文件過(guò)程即可;
若是分片計(jì)算導(dǎo)致過(guò)多的,則需要設(shè)置MaxInputSplitSize(最大數(shù)據(jù)分片大小)為一個(gè)大于默認(rèn)blockSize的值,越大map數(shù)量越少。
FileInputFormat.setMaxInputSplitSize(job,157286400); #默認(rèn)值是134217728(128M),157286400(150M)
?
或者設(shè)置一個(gè)container中運(yùn)行多個(gè)maptask任務(wù)
set mapred.job.reuse.jvm.num.tasks = 5;設(shè)置可以運(yùn)行5個(gè)maptask任務(wù)
?
個(gè)數(shù)過(guò)少,導(dǎo)致map端的并行度不高,資源沒(méi)有充分利用,大量工作時(shí)容易堵塞集群;
設(shè)置MaxInputSplitSize(最大數(shù)據(jù)分片大小)為一個(gè)小于默認(rèn)blockSize的值,越小map數(shù)量越多。
FileInputFormat.setMaxInputSplitSize(job,104857600); #默認(rèn)值是134217728(128M),104857600(100M)
?
?
5.合理設(shè)計(jì)reducetask的個(gè)數(shù)
reducetask決定的是map端出來(lái)的數(shù)據(jù)的走向
經(jīng)驗(yàn)值:上限: reducetask*0.95
在沒(méi)有達(dá)到上限之前 根據(jù)map端輸出的數(shù)據(jù)量和本身業(yè)務(wù)決定最終輸出的reducetask的個(gè)數(shù)
reducetask一旦設(shè)定 內(nèi)部的分區(qū):key.hash%reducetask
?
?
6.盡量不要使用in/exists,用left semi join代替
因?yàn)閕n/exists沒(méi)有關(guān)聯(lián)條件,而semi join有,hive擅長(zhǎng)有關(guān)聯(lián)條件的關(guān)聯(lián)。
?
?
7.多表插入時(shí),使用多重查詢,不要使用單重
單重:每插入一個(gè)表就要全表掃描一次stu表
insert into table stu01 select * from stu where age = 18; insert into table stu02 select * from stu where age = 19;
多重:僅掃描一次stu表
from stu insert into table stu01 select * where age = 18, insert into table stu02 select * where age = 19;
?
?
8.合理設(shè)計(jì)分區(qū)
為了減少全表掃描所耗費(fèi)的時(shí)間,將一些頻繁作為篩選條件的字段,設(shè)置為分區(qū)字段;
select * from stu where age =18;
未分區(qū)的時(shí)候,需要掃描stu全表;
以age字段分區(qū)后,僅掃描age=18的子表;
?
?
9.合理設(shè)計(jì)分桶
分桶的作用:
- 提高join的性能,分桶前:大表 join 大表 ; 分桶后:小表 join 小表;
- 提高抽樣的性能,分桶是按照hash算法分的,使得數(shù)據(jù)足夠散列;
怎么抽樣?語(yǔ)法:
tablesample(bucket x out of y);#y:桶簇的個(gè)數(shù),x:選擇第幾個(gè)桶簇
舉例:
1、stu表分了6個(gè)桶存儲(chǔ),將stu分成6個(gè)桶簇,取第1個(gè)桶簇的數(shù)據(jù)作為樣本
select * from stu tablesample(bucket 1 out of 6);
6個(gè)桶分成6個(gè)桶簇,則一個(gè)桶簇中正好是一個(gè)完整的桶,取第1個(gè)桶簇等同于取第一個(gè)桶中的數(shù)據(jù)。
?
2、stu表分了6個(gè)桶存儲(chǔ),將stu分成12個(gè)桶簇,取第1個(gè)桶簇的數(shù)據(jù)作為樣本
select * from stu tablesample(bucket 1 out of 12);
6個(gè)桶分成12個(gè)桶簇,則一個(gè)桶簇中只有半個(gè)桶,取第1個(gè)桶簇等同于取第一個(gè)桶中的上一半數(shù)據(jù)
?
3、stu表分了6個(gè)桶存儲(chǔ),將stu分成3個(gè)桶簇,取第1個(gè)桶簇的數(shù)據(jù)作為樣本
select * from stu tablesample(bucket 1 out of 3);
6個(gè)桶分成3個(gè)桶簇,則一個(gè)桶簇中有兩個(gè)桶,但是,第一個(gè)桶簇中并非是第1個(gè)桶和第2個(gè)桶的數(shù)據(jù),而是第1個(gè)和第1+3=4個(gè)桶中的數(shù)據(jù),以此類推:
- 第 1 個(gè)桶簇:第 1 桶 + 第 4 桶的數(shù)據(jù);
- 第 2 個(gè)桶簇:第 2 桶 + 第 5 桶的數(shù)據(jù);
- 第 3 個(gè)桶簇:第 3 桶 + 第 6 桶的數(shù)據(jù);
?
?
10.join的優(yōu)化
1、先過(guò)濾再join匹配,最大限度的減少參與join匹配的數(shù)據(jù)量;
2、大表 join 小表 ,最好啟動(dòng)mapjoin
如果沒(méi)有啟動(dòng)MapJoin,那么Hive解析器會(huì)在Reduce階段完成join,整個(gè)過(guò)程包含Map、Shuffle、Reduce階段,在在Shuffle階段時(shí)要進(jìn)行的大量數(shù)據(jù)傳輸,若在Map階段完成join,則節(jié)省了數(shù)據(jù)傳輸?shù)臅r(shí)間。
為了讓小表和大表可以進(jìn)入同一個(gè)map中處理,可以小表文件復(fù)制到每一個(gè)Map任務(wù)的本地,再讓Map把文件讀到內(nèi)存中待用。
參考文章:https://www.cnblogs.com/qiuhong10/p/7698277.html
https://blog.csdn.net/shudaqi2010/article/details/89505599
在Hive0.11后,可以通過(guò)以下兩個(gè)屬性來(lái)設(shè)置該優(yōu)化的觸發(fā)時(shí)機(jī)
set hive.auto.convert.join=true; hive.mapjoin.smalltable.filesize=25000000?; #25M
?
總結(jié)
以上是生活随笔為你收集整理的hive - 可优化的 10 个地方及详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: wp博客链接.html,WordPres
- 下一篇: 随机森林-集成学习方法(分类)