flinksqlleftjoin数据倾斜问题解决
1. 问题描述
原sql:
select a.user_id, a.其他字段, b.其他字段
from temp.user_log as a
left join user_info as b
on a.user_id = b.user_id
flink sql on hive,使⽤了left join去关联字典表,由于字典表中某⼀个值对应的左边记录表中的数据条数⾮常⾮常多,是其他字典值的数⼗倍之多,因此在join时发⽣了数据倾斜,这⼀个字典值对应的所有记录都跑到了⼀个并⾏度中,如下图所⽰:
其他并⾏度接收的数据量远远⼩于第⼀个并⾏度。
2. 解决步骤
2.1 字典表数据扩展
将字典表数据进⾏扩展。
⽐如字典表为⽤户信息,和记录表的关联字段为⽤户id,则可以在⽤户id后⾯添加从0~9的数字,将其扩展为原来的⼗倍,⽰例sql如下所⽰:
insert into temp.user_info_10
select concat(user_id, '0') as user_id, 其他字段值保持不变
from temp.user_info
;
insert into temp.user_info_10
select concat(user_id, '1') as user_id, 其他字段值保持不变
from temp.user_info
;
insert into temp.user_info_10
select concat(user_id, '2') as user_id, 其他字段值保持不变
from temp.user_info
;
...
上⾯⼀个10个sql语句,在⽤于关联的字段“⽤户id”后⾯拼接0~9的数字,将原字典表数据扩展为原来的10倍。
2.2 left join
当⽤户⽇志表和⽤户字典表关联时,需要将⽤户⽇志表的“⽤户id”字段后⾯拼接上0~9的数字,两个⽬的:
1. 和字典表进⾏关联,能够到对应的值。由于两边都在字段值后⾯添加了指定范围内的数字,因此肯定可以关联上,⽽且结果和原sql
⼀致。
2. 将⽤户⽇志记录数据中的“⽤户id”打散到不同的并⾏度,解决数据倾斜问题。
⽰例SQL:
select a.user_id, a.其他字段, b.其他字段
from temp.user_log as a
left join user_info_10 as b
on concat(a.user_id, cast(rand() * 10 as int) = b.user_id
运⾏过程图:
可以看到,和原sql相⽐,数据倾斜已经不是特别严重了。
3. 其他倾斜情况
如果记录表中的某个⽤户,在字典表中并不存在,但是这个⽤户的的⽇志⾮常多,造成了严重的数据倾斜,此时就不⽤扩展字典表了,直接将对该⽤户的id进⾏随机数拼接,然后打散该⽤户的记录,关联时使⽤该⽤户拼接之后的id进⾏关联即可。
由于该⽤户原id就⽆法关联到字典表数据,所以打散之后也关联不到字典表数据,对结果⽆影响。
⽰例sql如下:
select a.user_id, a.其他字段, b.其他字段
from
(
select
user_id,
case
when user_id = '记录最多,但是字典表中没有的⽤户id' then concat(user_id, cast(cast(rand(10) * 10 as int) as string)) else user_id end
as user_id_join,
其他字段
from temp.user_logsql left join 多表连接
) as a
left join user_info as b
on a.user_id_join = b.user_id
;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论