问题背景
技术最近在做数据溯源重构优化,计划使用业务方的数据跑数据任务,以解决数据质量问题。
过程中,碰到这样一个case:某数据需要join n张Hive表提数据,其中有这样一个业务逻辑要关联出mmm文章的mmm账号信息,文章表记录数xxx亿+,账号表yyy万+,这种数据关系导致在跑MR任务时数据倾斜,某个reduce要处理大部分数据,任务跑了20多个小时没有完成
问题原因
-
Hive多表join时,每个join会生成一个MR任务,并以join on条件作为reduce的hash_key
-
由于业务上不是所有的文章都是pgc发文,文章表里就会有大量mmm账号外键值为空的数据,约zz亿+
-
就是说zz亿+的数据只能被一个reduce处理,进而导致任务不能按预期完成
解决方案
引入随机ID解决数据倾斜:文章表在join账号表时做判断,如果账号外键为空,生成随机ID保证hash_key均匀分布
最佳实践
在问题排查过程中除了通过随机数解决hash_key分布不均的问题,还有几个优化点:
1. 只查任务相关的数据
a. 只查询用到的字段
b. 过滤掉任务无关的数据
2. 按数据存储从小到大的顺序关联从表
a. 内容详情表xxxT
b. 最原始一版HQL是先join了内容详情表,任务执行时间也特别长(并且任务执行过程中从一开始就占用较大的存储资源)
c. 调整表关联顺序,最后join内容详情表,任务执行符合预期
3. 关于语句嵌套,很早之前写HQL当时有一个规范,关联多个从表时一定要通过嵌套子查询的方式,在同一层级只join一张表(具体原因暂不详!!!)
上面提到的2个优化点的本质跟MR实现机制相关:MR过程中M的结果只有落盘后,才能被后续环节获取到。这就很好解释了:宽表由n张表的数据join出来,从MR的过程看会生成4个job,如果第一个job就关联使用了xxxT的数据,那么后面3个job也要处理xxxT+的数据(网络、磁盘IO、shuffle都很耗时)














网友评论