1. 程式人生 > >Hive Sort Merge Bucket Map Join(大表關聯)

Hive Sort Merge Bucket Map Join(大表關聯)

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掉了!