Sort MergeBucket Map Join(简称SMB Map Join)
基于Bucket Map Join。
条件要求
-
参与join的表均为分桶表,且需保证分桶内的数据是有序的
-
且分桶字段、排序字段和关联字段为相同字段
-
且其中一张表的分桶数量是另外一张表分桶数量的整数倍
与Bucket Join对比
相同点:同样是利用两表各分桶之间的关联关系,在分桶之间进行join操作
不同点:
分桶之间的join操作的实现原理。
Bucket Map Join,两个分桶之间的join实现原理为Hash Join算法;
而SMB Map Join,两个分桶之间的join实现原理为Sort Merge Join算法。
特点
Hive中的SMB Map Join在进行Join操作时
Map端是无需对整个Bucket构建hash table,也无需在Map端缓存整个Bucket数据
每个Mapper只需按顺序逐个key读取两个分桶的数据进行join即可。
触发方式
两种触发方式,包括Hint提示和自动转换。Hint提示已过时,不推荐使用。
--启动Sort Merge Bucket Map Join优化
set hive.optimize.bucketmapjoin.sortedmerge=true;
--使用自动转换SMB Join
set hive.auto.convert.sortmerge.join=true;
例子
首先需要依据源表创建两个的有序的分桶表
order_detail建议分16个bucket
payment_detail建议分8个bucket
注意分桶个数的倍数关系以及分桶字段和排序字段
--订单表
hive (default)>
drop table if exists order_detail_sorted_bucketed;
create table order_detail_sorted_bucketed(
id string comment '订单id',
user_id string comment '用户id',
product_id string comment '商品id',
province_id string comment '省份id',
create_time string comment '下单时间',
product_num int comment '商品件数',
total_amount decimal(16, 2) comment '下单金额'
)
clustered by (id) sorted by(id) into 16 buckets
row format delimited fields terminated by '\t';
--支付表
hive (default)>
drop table if exists payment_detail_sorted_bucketed;
create table payment_detail_sorted_bucketed(
id string comment '支付id',
order_detail_id string comment '订单明细id',
user_id string comment '用户id',
payment_time string comment '支付时间',
total_amount decimal(16, 2) comment '支付金额'
)
clustered by (order_detail_id) sorted by(order_detail_id) into 8 buckets
row format delimited fields terminated by '\t';
然后向两个分桶表导入数据
--订单表
hive (default)>
insert overwrite table order_detail_sorted_bucketed
select
*
from order_detail
where dt='2020-06-14';
--分桶表
hive (default)>
insert overwrite table payment_detail_sorted_bucketed
select
*
from payment_detail
where dt='2020-06-14';
最后在重写SQL语句
hive (default)>
select
*
from order_detail_sorted_bucketed od
join payment_detail_sorted_bucketed pd
on od.id = pd.order_detail_id;