一:hive中的三種join
1.map join
應用場景:小表join大表
一:設置mapjoin的方式:
)如果有一張表是小表,小表將自動執行map join。
默認是true。
<property>
<name>hive.auto.convert.join</name>
<value>true</value>
</property>
)判斷小表
<property>
<name>hive.mapjoin.smalltable.filesize</name>
<value>25000000</value>
</property>
二:隱式執行
/*+ MAPJOIN(tb_name) */
兩種方式說明:

2.reduce join
應用場景:大表join大表
但是效率不高。
3.SMB join(sort merger bucket):hash取余
排序合並桶。
條件:A桶個數必須與B桶的個數相同,或者B桶的個數是A桶的個數的倍數
例如:
A:4
B:8
——》A的每一個桶joinB桶的兩個小桶就可以了。
設置:
hive.auto.convert.sortmerge.join=true
二:數據傾斜
1.原因
指在mapreduce中某一個值數據量過多,導致reduce的負載不均衡
主要分為
join
group by
三:參考數據傾斜
1.鏈接
https://my.oschina.net/leejun2005/blog/178631
2.前言
在做Shuffle階段的優化過程中,遇到了數據傾斜的問題,造成了對一些情況下優化效果不明顯。
主要是因為在Job完成后的所得到的Counters是整個Job的總和,優化是基於這些Counters得出的平均值,而由於數據傾斜的原因造成map處理數據量的差異過大,
使得這些平均值能代表的價值降低。Hive的執行是分階段的,map處理數據量的差異取決於上一個stage的reduce輸出,所以如何將數據均勻的分配到各個reduce中,就是解決數據傾斜的根本所在。
3.操作
其實就兩種,因為,count distinct的底層就是group by。

4.原因
1)、key分布不均勻
2)、業務數據本身的特性
3)、建表時考慮不周
4)、某些SQL語句本身就有數據傾斜
5.表現
任務進度長時間維持在99%,查看任務監控頁面,發現只有少量的reduce子系統未完成。
單一的reduce的記錄與平均記錄差距過大,通常達到3倍甚至更多。
四:解決方案
1.主要針對的group by
map的combiner
hive.groupby.skewindata
替換值,將不要的值替換掉,然后過濾掉。
2.參數調節
)hive.map.aggr=true
map端的combiner,提前聚合一下。
)hive.groupby.skewindata=true
不按照key進行分區,map端的結果到了reduce后就進行一次聚合,達到reduce負載均衡。
這時,再進行一次mapreduce,group by key 分布到reduce,實現最終的聚合。
2.SQL調節
)如何Join:
關於驅動表的選取,選用join key分布最均勻的表作為驅動表
做好列裁剪和filter操作,以達到兩表做join的時候,數據量相對變小的效果。
)大小表Join:
使用map join讓小的維度表(1000條以下的記錄條數) 先進內存。在map端完成reduce.
)大表Join大表:
把空值的key變成一個字符串加上隨機數,把傾斜的數據分到不同的reduce上,由於null值關聯不上,處理后並不影響最終結果。
)count distinct大量相同特殊值
count distinct時,將值為空的情況單獨處理,如果是計算count distinct,可以不用處理,直接過濾,在最后結果中加1。
如果還有其他計算,需要進行group by,可以先將值為空的記錄單獨處理,再和其他計算結果進行union。
)group by維度過小:
采用sum() group by的方式來替換count(distinct)完成計算。
五:業務場景(實際中會遇到的情況)
1.空值產生數據傾斜
)過濾
select * from log a
join users b
on a.user_id is not null
and a.user_id = b.user_id
union all select * from log a where a.user_id is null;
)賦予新的值
select *
from log a left outer join users b on case when a.user_id is null then concat(‘hive’,rand() ) else a.user_id end = b.user_id;
)比較
方法2比方法1效率更好,不但io少了,而且作業數也少了。
解決方法1中 log讀取兩次,jobs是2。解決方法2 job數是1 。
2適合無效 id (比如 -99 , ’’, null 等) 產生的傾斜問題。把空值的 key 變成一個字符串加上隨機數,就能把傾斜的數據分到不同的reduce上 ,解決數據傾斜問題。
2.不同的數據類型進行關聯
)原因
用戶表中user_id字段為int,log表中user_id字段既有string類型也有int類型。當按照user_id進行兩個表的Join操作時,默認的Hash操作會按int型的id來進行分 配,這樣會導致所有string類型id的記錄都分配到一個Reducer中。
)把數字類型轉換成字符串類型
select * from users a
left outer join logs b on a.usr_id = cast(b.user_id as string)
3.表不大不小
)解決
select /*+mapjoin(x)*/* from log a
left outer join (
select /*+mapjoin(c)*/d.*
from ( select distinct user_id from log ) c
join users d
on c.user_id = d.user_id
) x
on a.user_id = b.user_id;
