网站首页 > 技术文章 正文
1. 问题描述
原sql:
select a.user_id, a.其他字段, b.其他字段
flink sql on hive,使用了left join去关联字典表,由于字典表中某一个值对应的左边记录表中的数据条数非常非常多,是其他字典值的数十倍之多,因此在join时发生了数据倾斜,这一个字典值对应的所有记录都跑到了一个并行度中,如下图所示:
其他并行度接收的数据量远远小于第一个并行度。
2. 解决方案
2.1 字典表数据扩展
将字典表数据进行扩展。
比如字典表为用户信息,和记录表的关联字段为用户id,则可以在用户id后面添加从0~9的数字,将其扩展为原来的十倍,示例sql如下所示:
insert into temp.user_info_10select concat(user_id, '0') as user_id, 其他字段值保持不变insert into temp.user_info_10select concat(user_id, '1') as user_id, 其他字段值保持不变insert into temp.user_info_10select concat(user_id, '2') as user_id, 其他字段值保持不变
上面一个10个sql语句,在用于关联的字段“用户id”后面拼接0~9的数字,将原字典表数据扩展为原来的10倍。
2.2 left join
当用户日志表和用户字典表关联时,需要将用户日志表的“用户id”字段后面拼接上0~9的数字,两个目的:
- 和字典表进行关联,能够找到对应的值。由于两边都在字段值后面添加了指定范围内的数字,因此肯定可以关联上,而且结果和原sql一致。
- 将用户日志记录数据中的“用户id”打散到不同的并行度,解决数据倾斜问题。
示例SQL:
select a.user_id, a.其他字段, b.其他字段left join user_info_10 as bon concat(a.user_id, cast(cast(rand(10) * 10 as int) as int)) = b.user_id
运行过程图:
可以看到,和原sql相比,数据倾斜已经不是特别严重了。
3. 其他倾斜情况
如果记录表中的某个用户,在字典表中并不存在,但是这个用户的的日志非常多,造成了严重的数据倾斜,此时就不用扩展字典表了,直接将对该用户的id进行随机数拼接,然后打散该用户的记录,关联时使用该用户拼接之后的id进行关联即可。
由于该用户原id就无法关联到字典表数据,所以打散之后也关联不到字典表数据,对结果无影响。
示例sql如下:
select a.user_id, a.其他字段, b.其他字段 when user_id = '记录最多,但是字典表中没有的用户id' then concat(user_id, cast(cast(rand(10) * 10 as int) as string)) else user_id endon a.user_id_join = b.user_id
猜你喜欢
- 2025-02-03 彻底搞懂where,inner join,left join,right join,full join的区别
- 2025-02-03 FLINK-SQL之JOIN的6种方式(flink sql执行流程)
- 2025-02-03 详细介绍MySQL中的LEFT JOIN、INNER JOIN和RIGHT JOIN
- 2025-02-03 SQL关联各种JOIN傻傻分不清楚,读这一篇就够了
- 2025-02-03 2副图秒懂SQL中的join(sqljoin的用法)
- 2025-02-03 SQL JOIN 从入门到精通——看懂这张图,告别面试尴尬!
- 2025-02-03 浅析Sql中内连接、外连接、全连接、交叉连接的区别
- 2025-02-03 什么,LEFT JOIN 会变成 JOIN?(left join on in)
- 2025-02-03 left join中的on和where条件你真的理解了吗?
- 2025-02-03 初学者的一分钟SQL Join教程(sql技巧)
- 02-21走进git时代, 你该怎么玩?_gits
- 02-21GitHub是什么?它可不仅仅是云中的Git版本控制器
- 02-21Git常用操作总结_git基本用法
- 02-21为什么互联网巨头使用Git而放弃SVN?(含核心命令与原理)
- 02-21Git 高级用法,喜欢就拿去用_git基本用法
- 02-21Git常用命令和Git团队使用规范指南
- 02-21总结几个常用的Git命令的使用方法
- 02-21Git工作原理和常用指令_git原理详解
- 最近发表
- 标签列表
-
- cmd/c (57)
- c++中::是什么意思 (57)
- sqlset (59)
- ps可以打开pdf格式吗 (58)
- phprequire_once (61)
- localstorage.removeitem (74)
- routermode (59)
- vector线程安全吗 (70)
- & (66)
- java (73)
- org.redisson (64)
- log.warn (60)
- cannotinstantiatethetype (62)
- js数组插入 (83)
- resttemplateokhttp (59)
- gormwherein (64)
- linux删除一个文件夹 (65)
- mac安装java (72)
- reader.onload (61)
- outofmemoryerror是什么意思 (64)
- flask文件上传 (63)
- eacces (67)
- 查看mysql是否启动 (70)
- java是值传递还是引用传递 (58)
- 无效的列索引 (74)