1 數(shù)據(jù)傾斜概述
??數(shù)據(jù)傾斜指參與計(jì)算的數(shù)據(jù)分布不均,即某個key或者某些key的數(shù)據(jù)量遠(yuǎn)超其他key,導(dǎo)致在shuffle階段,大量相同key的數(shù)據(jù)被發(fā)往同一個Reduce,導(dǎo)致該Reduce所需的時間遠(yuǎn)超其他Reduce,成為整個任務(wù)的瓶頸。
??Hive中的數(shù)據(jù)傾斜常出現(xiàn)在分組聚合和join操作的場景中 。
2 分組聚合導(dǎo)致的數(shù)據(jù)傾斜
2.1 優(yōu)化說明
??Hive中未經(jīng)優(yōu)化的分組聚合,是通過一個MapReduce Job實(shí)現(xiàn)的。Map端負(fù)責(zé)讀取數(shù)據(jù),并按照分組字段分區(qū),通過Shuffle,將數(shù)據(jù)發(fā)往Reduce端,各組數(shù)據(jù)在Reduce端完成最終的聚合運(yùn)算。
??如果group by分組字段的值分布不均,就可能導(dǎo)致大量相同的key進(jìn)入同一Reduce,從而導(dǎo)致數(shù)據(jù)傾斜問題。
解決思路:
Map-Site聚合和Skew-GroupBy優(yōu)化。
1、Map-Side聚合
??開啟Map-Side聚合后,數(shù)據(jù)會現(xiàn)在Map端完成部分聚合工作(可以看作大小一樣的切片,相當(dāng)于先完成切片內(nèi)的聚合工作)。
??即便原始數(shù)據(jù)是傾斜的,經(jīng)過Map端的初步聚合后,發(fā)往Reduce的數(shù)據(jù)也就不再傾斜了。最佳狀態(tài)下,Map-端聚合能完全屏蔽數(shù)據(jù)傾斜問題。
相關(guān)參數(shù):
--啟用map-side聚合
set hive.map.aggr=true;
--用于檢測源表數(shù)據(jù)是否適合進(jìn)行map-side聚合。檢測的方法是:
--先對若干條數(shù)據(jù)進(jìn)行map-side聚合,若聚合后的條數(shù)和聚合前的條數(shù)比值小于該值,
--則認(rèn)為該表適合進(jìn)行map-side聚合;否則,認(rèn)為該表數(shù)據(jù)不適合進(jìn)行map-side聚合,
--后續(xù)數(shù)據(jù)便不再進(jìn)行map-side聚合。
set hive.map.aggr.hash.min.reduction=0.5;
--用于檢測源表是否適合map-side聚合的條數(shù)。
set hive.groupby.mapaggr.checkinterval=100000;
--map-side聚合所用的hash table,占用map task堆內(nèi)存的最大比例,
--若超出該值,則會對hash table進(jìn)行一次flush。
set hive.map.aggr.hash.force.flush.memory.threshold=0.9;
2、Skew-GroupBy優(yōu)化
??Skew-GroupBy專門用于處理由于group by導(dǎo)致數(shù)據(jù)傾斜的方案。
原理:
??啟動兩個MR任務(wù),第一個MR按照隨機(jī)數(shù)分區(qū),將數(shù)據(jù)分散發(fā)送到Reduce,完成部分聚合;
??第二個MR讀取第一個Reduce端的數(shù)據(jù)按照分組字段分區(qū),完成最終聚合。
相關(guān)參數(shù):
--啟用分組聚合數(shù)據(jù)傾斜優(yōu)化
set hive.groupby.skewindata=true;
2.2 案例
1、示例SQL語句
select
province_id,
count(*)
from order_detail
group by province_id;
2、優(yōu)化前
??表中的province_id字段是存在傾斜的,若不經(jīng)過優(yōu)化,通過觀察yarn中reduce任務(wù)的執(zhí)行過程,是能夠看出數(shù)據(jù)傾斜現(xiàn)象的。
??hive中的map-side聚合是默認(rèn)開啟的,若想看到數(shù)據(jù)傾斜的現(xiàn)象,需要先將hive.map.aggr參數(shù)設(shè)置為false。
3、優(yōu)化思路
(1)Map-Side聚合
設(shè)置參數(shù):
--啟用map-side聚合
set hive.map.aggr=true;
--關(guān)閉skew-groupby
set hive.groupby.skewindata=false;
執(zhí)行計(jì)劃:
??觀察yarn中reduce任務(wù)的執(zhí)行過程,很明顯可以看到開啟map-side聚合后,reduce數(shù)據(jù)不再傾斜。
(2)Skew-GroupBy優(yōu)化
設(shè)置參數(shù):
--啟用skew-groupby
set hive.groupby.skewindata=true;
--關(guān)閉map-side聚合
set hive.map.aggr=false;
??開啟Skew-GroupBy優(yōu)化后,可以很明顯看到該sql執(zhí)行在yarn上啟動了兩個mr任務(wù),第一個mr打散數(shù)據(jù),第二個mr按照打散后的數(shù)據(jù)進(jìn)行分組聚合。
2.3 總結(jié)
??Map-site優(yōu)化優(yōu)于Skew-GroupBy優(yōu)化,能做Map-site聚合就做Map-site聚合。
??Map-site聚合要在Map端維護(hù)一個HashTable,HashTable消耗了內(nèi)存,即內(nèi)存不充足的情況下盡量不做Map-site聚合,但也可以做,當(dāng)HashTable超過設(shè)定的內(nèi)存閾值時,會flush刷新。
??當(dāng)內(nèi)存很小時會flush很多次導(dǎo)致map端聚合沒有解決數(shù)據(jù)傾斜問題,此時可以用Skew-GroupBy聚合。也就是不管內(nèi)存足部足夠都能把數(shù)據(jù)打散再做聚合。
3 Join導(dǎo)致的數(shù)據(jù)傾斜
3.1 優(yōu)化說明
??未經(jīng)優(yōu)化的join操作,默認(rèn)是使用common join算法,也就是通過一個MapReduce Job完成計(jì)算。Map端負(fù)責(zé)讀取join操作所需表的數(shù)據(jù),并按照關(guān)聯(lián)字段進(jìn)行分區(qū),通過Shuffle,將其發(fā)送到Reduce端,相同key的數(shù)據(jù)在Reduce端完成最終的Join操作。
??如果關(guān)聯(lián)字段的值分布不均,就可能導(dǎo)致大量相同的key進(jìn)入同一Reduce,從而導(dǎo)致數(shù)據(jù)傾斜問題。
??由join導(dǎo)致的數(shù)據(jù)傾斜問題,有如下三種解決方案:map join、skew join、調(diào)整SQL語句。
1、map join
??map join中join操作僅在map端就能完成,沒有shuffle操作,沒有reduce階段,自然不會產(chǎn)生reduce端的數(shù)據(jù)傾斜。該方案適用于大表join小表時發(fā)生數(shù)據(jù)傾斜的場景。
原理:
??多個Mapper緩存小表數(shù)據(jù),大表數(shù)據(jù)進(jìn)行切片(切片只與大小有關(guān),與key無關(guān)),均勻切成若干個片,一個map負(fù)責(zé)處理一個切片(逐條遍歷然后找緩存的小表的數(shù)據(jù)join)再逐條輸出,使得每個map處理的數(shù)據(jù)量一致,解決數(shù)據(jù)傾斜問題。
相關(guān)參數(shù):
--啟動Map Join自動轉(zhuǎn)換
set hive.auto.convert.join=true;
--一個Common Join operator轉(zhuǎn)為Map Join operator的判斷條件,
--若該Common Join相關(guān)的表中,存在n-1張表的大小總和<=該值,則生成一個Map Join計(jì)劃,
--此時可能存在多種n-1張表的組合均滿足該條件,則hive會為每種滿足條件的組合均生成一個Map Join計(jì)劃,
--同時還會保留原有的Common Join計(jì)劃作為后備(back up)計(jì)劃,實(shí)際運(yùn)行時,
--優(yōu)先執(zhí)行Map Join計(jì)劃,若不能執(zhí)行成功,則啟動Common Join后備計(jì)劃。
set hive.mapjoin.smalltable.filesize=250000;
--開啟無條件轉(zhuǎn)Map Join
set hive.auto.convert.join.noconditionaltask=true;
--無條件轉(zhuǎn)Map Join時的小表之和閾值,若一個Common Join operator相關(guān)的表中
--存在n-1張表的大小總和<=該值,此時hive便不會再為每種n-1張表的組合均生成Map Join計(jì)劃,
--同時也不會保留Common Join作為后備計(jì)劃。而是只生成一個最優(yōu)的Map Join計(jì)劃。
set hive.auto.convert.join.noconditionaltask.size=10000000;
2、skew join
??skew join解決大表join大表出現(xiàn)數(shù)據(jù)傾斜的問題。
原理:
??為傾斜的大key單獨(dú)啟動一個map join任務(wù)進(jìn)行計(jì)算,其余key進(jìn)行正常的common join。
相關(guān)參數(shù):
--啟用skew join優(yōu)化
sethive.optimize.skewjoin=true;
--觸發(fā)skew join的閾值,若某個key的行數(shù)超過該參數(shù)值,則觸發(fā)(按照行數(shù)進(jìn)行檢測)
set hive.skewjoin.key=100000;
??這種方案對參與join的源表大小沒有要求,但是對兩表中傾斜的key的數(shù)據(jù)量有要求,要求一張表中的傾斜key的數(shù)據(jù)量比較小(方便走mapjoin)。
3、調(diào)整SQL語句
??若參與join的兩表均為大表,其中一張表的數(shù)據(jù)是傾斜的,可以對SQL語句進(jìn)行相應(yīng)的調(diào)整。
??假設(shè)原始SQL語句如下:A,B兩表均為大表,且其中一張表的數(shù)據(jù)是傾斜的。
select
*
from A
join B
on A.id=B.id;
??圖中1001為傾斜的大key,被發(fā)往了同一個Reduce進(jìn)行處理。
調(diào)整SQL語句如下:
select
*
from(
select --打散操作,加隨機(jī)數(shù)0、1
concat(id,'_',cast(rand()*2 as int)) id,
value
from A
)ta
join(
select --擴(kuò)容操作
concat(id,'_',0) id,
value
from B
union all
select
concat(id,'_',1) id,
value
from B
)tb
on ta.id=tb.id;
調(diào)整之后的SQL語句執(zhí)行計(jì)劃:
3.2 案例
1、示例SQL語句
select
*
from order_detail od
join province_info pi
on od.province_id=pi.id;
2、優(yōu)化前
--關(guān)閉Map Join自動轉(zhuǎn)換
set hive.auto.convert.join=false;
--關(guān)閉skew join優(yōu)化(默認(rèn)為關(guān)閉狀態(tài))
sethive.optimize.skewjoin=false;
??order_detail表中的province_id字段是存在傾斜的,若不經(jīng)過優(yōu)化,觀察yarn中的reduce任務(wù)可以看到數(shù)據(jù)傾斜的現(xiàn)象。
??hive中的map join自動轉(zhuǎn)換是默認(rèn)開啟的,若想看到數(shù)據(jù)傾斜的現(xiàn)象,需要先將hive.auto.convert.join參數(shù)設(shè)置為false。
3、優(yōu)化思路
(1)map join
設(shè)置參數(shù):
--啟用map join
set hive.auto.convert.join=true;
--關(guān)閉skew join
set hive.optimize.skewjoin=false;
??可以很明顯看到開啟map join以后,mr任務(wù)只有map階段,沒有reduce階段,沒有數(shù)據(jù)傾斜發(fā)生。
(2)skew join
設(shè)置參數(shù):文章來源:http://www.zghlxwxcb.cn/news/detail-568392.html
--啟動skew join
set hive.optimize.skewjoin=true;
--關(guān)閉map join
set hive.auto.convert.join=false;
開啟skew join后,使用explain查看執(zhí)行計(jì)劃:
??skew join生效,任務(wù)既有common join,又有部分key走了map join。并且該sql在yarn上最終啟動了兩個mr任務(wù),而且第二個任務(wù)只有map沒有reduce階段,說明第二個任務(wù)是對傾斜的key進(jìn)行了map join。文章來源地址http://www.zghlxwxcb.cn/news/detail-568392.html
到了這里,關(guān)于【大數(shù)據(jù)之Hive】二十三、HQL語法優(yōu)化之?dāng)?shù)據(jù)傾斜的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!