Map Join算法的改进
可用于大表join大表的场景
核心思想
原本Map Join中的第二个Job的Map端就无需再缓存小表的全表数据了
而只需缓存其所需的分桶即可。
条件:
参与join的表均为分桶表,且关联字段为分桶字段
并且其中一张表的分桶数量是另外一张表分桶数量的整数倍
就能保证参与join的两张表的分桶之间具有明确的关联关系
所以就可以在两表的分桶间进行MapJoin操作了
参数
Bucket MapJoin不支持自动转换
通过用户在SQL语句中提供如下Hint提示并配置相关参数
hive (default)>
select /*+ mapjoin(ta) */
ta.id,
tb.id
from table_a ta
join table_b tb on ta.id=tb.id;
--关闭cbo优化,cbo会导致hint信息被忽略
set hive.cbo.enable=false;
--map join hint默认会被忽略(因为已经过时),需将如下参数设置为false
set hive.ignore.mapjoin.hint=false;
--启用bucket map join优化功能
set hive.optimize.bucketmapjoin = true;
举例
首先需要依据源表创建两个分桶表
order_detail建议分16个bucket
payment_detail建议分8个bucket
注意分桶个数的倍数关系以及分桶字段。
--订单表
hive (default)>
drop table if exists order_detail_bucketed;
create table order_detail_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) into 16 buckets
row format delimited fields terminated by '\t';
--支付表
hive (default)>
drop table if exists payment_detail_bucketed;
create table payment_detail_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) into 8 buckets
row format delimited fields terminated by '\t';
然后向两个分桶表导入数据
--订单表
hive (default)>
insert overwrite table order_detail_bucketed
select
*
from order_detail
where dt='2020-06-14';
--分桶表
hive (default)>
insert overwrite table payment_detail_bucketed
select
*
from payment_detail
where dt='2020-06-14';
然后设置以下参数
最后在重写SQL语句
hive (default)>
select /*+ mapjoin(pd) */
*
from order_detail_bucketed od
join payment_detail_bucketed pd on od.id = pd.order_detail_id;
执行计划查看
Bucket Map Join的执行计划的基本信息和普通的Map Join无异
若想看到差异,可执行如下语句,查看执行计划的详细信息
hive (default)>
explain extended select /*+ mapjoin(pd) */
*
from order_detail_bucketed od
join payment_detail_bucketed pd on od.id = pd.order_detail_id;
详细执行计划中,如在Map Join Operator中看到 “BucketMapJoin:true”
则表明使用的Join算法为Bucket MapJoin