Hive Sort Merge Bucket Map Join(大表關聯)
阿新 • • 發佈:2019-01-31
Hive 桶
對於每一個表(table)或者分割槽, Hive可以進一步組織成桶,也就是說桶是更為細粒度的資料範圍劃分。Hive也是 針對某一列進行桶的組織。Hive採用對列值雜湊,然後除以桶的個數求餘的方式決定該條記錄存放在哪個桶當中。
把表(或者分割槽)組織成桶(Bucket)有兩個理由:
(1)獲得更高的查詢處理效率。桶為表加上了額外的結構,Hive 在處理有些查詢時能利用這個結構。具體而言,連線兩個在(包含連線列的)相同列上劃分了桶的表,可以使用 Map 端連線 (Map-side join)高效的實現。比如JOIN操作。對於JOIN操作兩個表有一個相同的列,如果對這兩個表都進行了桶操作。那麼將儲存相同列值的桶進行JOIN 操作就可以,可以大大較少JOIN的資料量。
(2)使取樣(sampling)更高效。在處理大規模資料集時,在開發和修改查詢的階段,如果能在資料集的一小部分資料上試執行查詢,會帶來很多方便。
測試:一個4000萬和一個5000多萬的表Join,關聯鍵資料傾斜,並且笛卡爾積,效果明顯。
建立小表
create table lxw_test1(id int,name string,date_time string)
clustered by(id) sorted by(id) into 10 buckets;
建立大表
create table lxw_test2(id int,name string,date_time string)
clustered by(id) sorted by(id) into 5 buckets;
ps:
1.兩個表關聯鍵為id,需要按id分桶並且做排序,小表的分桶數是大表分桶數的倍數。
2.對於map端連線的情況,兩個表以相同方式劃分桶。處理左邊表內某個桶的 mapper知道右邊表內相匹配的行在對應的桶內。因此,mapper只需要獲取那個桶 (這只是右邊表記憶體儲資料的一小部分)即可進行連線。這一優化方法並不一定要求 兩個表必須桶的個數相同,兩個表的桶個數是倍數關係也可以
3.桶中的資料可以根據一個或多個列另外進行排序。由於這樣對每個桶的連線變成了高效的歸併排序(merge-sort), 因此可以進一步提升map端連線的效率
啟用桶表
set hive.enforce.bucketing = true;
往小表中插入4000萬條記錄
insert overwrite table lxw_test1
select id,name,null
from woa_all_user_info_his
where pt = '2012-05-28'
limit 40000000;
往大表中插5000多萬條記錄(woa_all_user_info_his中有5000多萬條記錄)
insert overwrite table lxw_test2
select id,name,date_time
from woa_all_user_info_his
where pt = '2012-05-28';
設定Sort Merge Bucket Map Join的引數
set hive.optimize.bucketmapjoin = true;
set hive.optimize.bucketmapjoin.sortedmerge = true;
set hive.input.format=org.apache.hadoop.hive.ql.io.BucketizedHiveInputFormat;
ps:此時的狀況是Bucket columns==Join Columns==Sort Columns,完全具備具備使用Sort Merge Bucket Map Join的條件。
查詢
select /*+ mapjoin(b) */ count(1)
from lxw_test1 a
join lxw_test2 b
on a.id = b.id
測試結果:
包括insert資料,採用Sort Merge Bucket Map Join的方式耗時10分鐘左右。
如果這兩個表做普通的join,耗時1個多小時,還跑不完,最後只得Kill掉了!