hive性能优化使用map join
在实际业务逻辑中经常进行两张表的join,不管是两张大表关联还是一张大表一张小表关联会出现经常数据倾斜。下面介绍一下我在工作使用的总结:
原始数据page_test
原始数据city
1.Common join原理(select a.user_id,a.city,b.name from page_test a left outer join city b )注意:
1.map端的操作key为两张表on条件的列,value为select列+表tag
2.将同一key分配到reduce端,然后根据表tag进行笛卡尔积join
2.map join原理 启动本地的一个Task A,它负责扫描小表b的数据同时转换为HashTable的数据结构,并将文件加载到DistributeCache后分发到大表的每个map中然后进行join操作。
总结:
1.map join无reduce操作,所以没有shuffle。这样可以减少大量的网络I/O。(如:大表文件数500、文件250M,小表20M。map join的网络I/O共50020M,Common join的网络I/O共500250M+20M),同时不需要进行map sort和shuffle sort排序。
2.由于Common join的一个reduce包含两张表的数据,所以进行reduce的join先将一张表的数据加载到内存后才能跟另外一张表的数据join,如果加载的是大表需要reduce大量的内存。
3.由于小表转换为HashTable结构,map join在对数据进行join很快,哈希算法的时间为O(1)。
4.map join需要将小表加载DistributeCache是存在Driver内,大表map从Driver拉取小表数据。所以小表数据量不宜过大。
3. 将Common join转化为map join方法
1.b表比较小直接设置hive相关参数即可。
2.通过谓词下推将b表进行筛选使b表够小。
比如:select
a.id,
b.id
from test_1 a
left outer join
(
select
id
from test_2
where id>xx and id<xx
) b on a.id=b.id
3.实际业务中a表很多情况下只包含b表的一部分,可以只提取这一部分用户出来。比如a表为用户浏览日志,b表为用户表,但是当天浏览用户毕竟只是用户的一部分。
select
a.id,
b.name
from page a
left outer join
(
select
b.id,
b.name
from
(
select
id
from page
group by
id
) a ,user b
where a.id=b.id
) b on a.id=b.id
4.两张大表进行关联时,出现数据倾斜一种优化方法是将TopN量ID的join加上非TopN量ID的join,一般情况下TopN量的ID是固定。如果不是固定可以跟3一样来进行。
比如:
select
a.id,
b.name
from page a
left outer join
(
select
b.id,
b.name
from
(
select
id,
count(*)cnt
from page
group by
id
order by cnt
limit N
) a ,user b
where a.id=b.id
) b on a.id=b.id