数据倾斜常见场景

  • 表表关联
    • 大小表关联
    • 大表间关联(转化为大小表关联问题)
    • 关联键含大量空值
    • 关联键数据类型不一致
  • Group by逻辑
  • count(distinct):set hive.cbo.enable = true

1.大小表关联-mapjoin参数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
create table DB_NAME.TB_NAME as
with tmp_xxx as(

select
     xxx.xxx
    ,xxx.yyy
    ,...
    ,row_number()over(partition by ... desc) as xxx
from DB_NAME.xxx as xxx
)
select
    a.xxx
   ,a.yyy
    ...
   ,b.biz_date
from DB_NAME.xxx_his a
left outer join(
select
    tmp_xxx.xxx
    ,tmp_xxx.yyy
    ...
    ,tmp xxx.id
from tmp_xxx
where tmp_xxx.id =1
) b
on a.rtl_xxx_id = b.rtl_xxx_id
left outer join DB NAME.xxx_cls c
on b. prod_xxx_id = c.prod_xxx_id

在即席查询页面提交以上代码后,通过日志发现

image-20230329205451882

在 525.23s 开始一直有一个节点长时间运行,此时其他所有节点都已经完成。推测发生了数据倾斜。

数据探源

探查相应表信息 DESC formatted 项目名.表名

发现表a数据量达30亿以上且为分区表,子查询结果b的数据量大10w+,表c为300+。

查看关联键信息
1
2
3
4
5
6
select  关联键,count(1) 
from 表名 
where 
group by 关联键
having count(1) > 1 
order by count(1) desc

查到表a关联键的分布情况

00Axxx 1204325436
53xxx 386342436
35xxx 465

发现大小表关联时候关联键数量分布极其不均匀引起的,此时可以通过开启mapjoin参数进行优化。

  • set hive.auto.convert.join = true

原理:由Reduce Join调整为Map Join,使其在Map端完成链接,省去Reduce端步骤。避免了大量同一个关联键落到了同一节点的可能性。

  • 增加hint关键字 /* + mapjoin(表别名) */

原理:将关键字内的表强行加载入内存进行操作。

注意:不提倡将任何表都用hint关键字加载进内存,会造成内存溢出。

1
2
3
4
5
6
7
select 
/* + mapjoin(b,c) */
a 
left join b 
on ...
left join c 
on ...

2.关联键含有空值-空值打散或过滤

空值的特性

  • 空值字段作为关联键时,并不会参与链接
  • 空值字段作为关联键时,拥有相同的key值,会被分发到同一任务节点

image-20230329212438819

处理方式1:

过滤空值。提前将数据按关联键是否为空拆成两部分,关联后再将两部分数据进行合并。

如有需要可以开启并行parallel参数,再直接使用union all合并。

parallel参数:set hive.exc.parallel = true; – 默认为false

处理方式2:

打散空值关联键,如图。

3.关联键数据类型不一致-cast()函数

强制转化数据类型后可能会因为精度丢失等原因引发数据倾斜。

一般建议统一转换成string类型进行关联。

4.Group by导致-skewindata参数

set hive.groupby.skewindata = true; --默认false

skewindata参数:

表现:由一个 Reducer 转变成两个Reducer。

第一个 Reducer 的作用:随机接收Map端输入的数据,达到负载均衡的目的。

第二个 Reducer 的作用:按照相同的 Groupby key,做最终聚合的操作。

开启参数前:

image-20230329213525836

开启参数后:

image-20230329213600568

在平时任务优化过程中发现,在执行速度上平均可以提升 80% 左右。