hive中的join操作及其數據傾斜
join操作是一個大數據領域一個常見的話題。歸根結底是由于在數據量超大的情況下,join操作會使內存占用飆升。運算的復雜度也隨之上升。在進行join操作時,也會更容易發生數據傾斜。這些都是需要考慮的問題。
過去了解到很多關于join操作的知識點,特此總結一下。
join操作可以分為三類:小表join小表、大表join小表、大表join大表
其中小表join小表是不需要考慮的,不會存在內存溢出,也不會因為數據傾斜導致查詢緩慢。
一、大表join小表
大表join小表的解決方法也相對簡單,那就是map-side-join。
所謂map-said-join就是將小表直接長期駐留在內存中,在map端完成join操作。
hive通過如下配置開啟map-said-join:
SET hive.auto.convert.join=true;
SET hive.mapjoin.smalltable.filesize=25000000;
其中,hive.auto.convert.join
參數表示是否自動轉換為mapjoin,hive.mapjoin.smalltable.filesize
參數表示小表的大小閾值。如果小表的大小超過這個閾值,那么Hive將不會自動轉換為mapjoin。
編寫帶有join操作的sql語句時要將小表放在join語句的右邊,如下:
SELECT /*+MAPJOIN(small_table)*/ large_table.col1, small_table.col2
FROM large_table JOIN small_table
ON large_table.key = small_table.key;
二、大表join大表
大表join大表最常用的方法是bucket-map-join,即將大表拆分成小表,小表再做join操作。
所謂bucket-map-join就是將兩個要進行join操作的表的join key上做hash bucket,將兩張大表分成多張小表。join key經過hash后的值相同就分到同一個表中,此時只需要將hash相同的bucket進行join操作即可。需要注意的是,兩個大表中較大的那個表所得出的hash bucket個數應該是較小的表所得出的hash bucket個數的整數倍。
各個小表依然復制到大表所在的map進行mapjoin
實現bucket-map-join的條件
1.啟動bucket-map-join,set hive.optimize.bucketmapjoin = true;
2.一個表的bucket數是另一個表bucket數的整數倍
3.bucket列就是join key所在的列
4.必須是應用在map-join場景中
另一種大表join大表常用的方法是SMB join(Sort Merge Bucket Join)
SMB join相比于bucket-map-join而言多了兩個限制條件:
1.要求必須有序
2.要求兩個大表所生成的bucket數必須相同
下表給出兩者對比:
bucket map join | SMB join |
---|---|
set hive.optimize.bucketmapjoin = true; | set hive.optimize.bucketmapjoin = true;set hive.auto.convert.sortmerge.join=true;set hive.optimize.bucketmapjoin.sortedmerge = true;set hive.auto.convert.sortmerge.join.noconditionaltask=true; |
一個表的bucket數是另一個表bucket數的整數倍 | 兩個表的bucket數必須相同 |
bucket列 == join列 | bucket列 == join列 |
必須是應用在map join的場景中 | 必須是應用在bucket map join 的場景中 |
需要注意的是,用戶需要自己保證SMB join時數據的有序。如果不是有序的,會導致結果出錯。
1.hive.enforce.sorting設置為true。開啟強制排序時,插數據到表中會進行強制排序,默認false
2.插入數據時可以在sql中使用distributed c1 sort by c1 或者cluster by c1
另外,表創建時必須時CLUSTERED且SORTED,如下:
create table test_smb_2(mid string,age_id string)
CLUSTERED BY(mid) SORTED BY(mid) INTO 500 BUCKETS;
##三、join操作中的數據傾斜
如果在join操作的過程中發生數據傾斜,那么就需要采用skew join來解決
skew join的打開方式:
#運行時
set hive.optimize.skewjoin=true;
#編譯期
set hive.optimize.skewjoin.compiletime=true;
#開啟union優化
set hive.optimize.union.remove=true;
skew join對于數據傾斜的解決方案就是單獨開一個新的job,并對發生傾斜的數據進行map join。兩個任務完成后使用union將結果進行拼接。