spark 数据倾斜优化总结

一、数据倾斜产生原因

数据倾斜就是部分task承担了过多的计算任务,导致整个stage都被卡。

可能产生数据倾斜的场景如下

操作 场景
join 其中一个表比较小,但key值少
join 大表与大表,但key值中存在过多的特殊值,如0或null
join on条件包含key值过滤逻辑,导致部分数据被保留,部分被过滤,最终节点分布不均
join 多对多关系表join导致数据膨胀
group by 某个组合数量特别多
count distinct 需要集中最后一个reduce节点处理,特殊值多就会慢
使用脚本或udf 会存在强制数据分布在少量节点的可能
distriute by 存在值不均匀的可能
读取 上游文件数过少,单个文件过大

二、数据倾斜优化

2.1 调参优化

参数 作用 备注
hive.map.aggr=true map端部分聚合 仅适用于hive引擎,不适用于spark。spark本身就支持map端的局部聚合
hive.groupby.skewindata=true 参数设置为true时,生成的查询计划会有2个MR job。第一个MR中,map的输出结果会随机分配到reduce中,每个reduce做部分聚合操作,并输出结果,这样相同的key会被分发到不同的reduce中,起到了负载均衡的目的,第二个MR再根据第一个MR预处理的结果,完成聚合操作 仅适用于hive引擎,spark不支持此参数

2.2 代码优化

2.2.1 join类操作

  1. 如果是join操作,那么采用join key分布最均匀的表作为驱动表
  2. where类的操作在join前进行
2.2.1.1 小表join大表

使用 /*+mapjoin(a)*/ 让小的维度表先进内存,在map端完成reduce

使用此操作需要对小的维度表配置DQC数据量监控,以避免进入内存的维表数据过大

2.2.1.2 中表join大表

在维表大小中等,完全进入内存可能报错;但日志与维表关联部分出现某种行为的维值较少时,可以采用两次 mapjoin 的方式优化倾斜问题。例,有交易日志log,和维表dim,它们2次join示例如下

sql 复制代码
select /*+mapjoin(b)*/
    a.*, 
    b.*
from log a
left join (
    select /*+mapjoin(d)*/
           c.*
      from dim AS c
            join (
                select dim_id
                 from log
                group by dim_id
            ) AS d 
            on c.dim_id = d.dim_id
    ) AS b 
 on a.dim_id = b.dim_id
2.2.1.3 大表join大表

大表join大表一般由于key值存在 null 等特殊值,导致数据过于集中倾斜。这种情况可以使用hash函数将key打散。这里不要用rand,因为fetch failed后,整个job会被kill

2.2.1.4 join条件包含key值过滤逻辑

尽量在join前使用where过滤

2.2.1.5 多对多关系表join
  1. 去掉热点大key
  2. 增加关联条件
  3. 减少数据范围,笛卡尔积结果尽量控制1亿

2.2.2 group by操作

将倾斜数据拿出来单独处理,后面再union 回去

2.2.3 count distinct操作

2.2.3.1 单个 count distinct

可以将它转换为count+group by。如果单个值数据量比较集中,可以过滤该值,结果+1.

下面的示例是从t表中取user_id的uv。其中,user_id有大量为0的异常值

优化前

sql 复制代码
select count(distinct user_id) as uv from t

优化后

sql 复制代码
select count(user_id) +1 as uv
   from (
   	select user_id
   	  from t
   	 where user_id != 0
   	 group by user_id
)
2.2.3.1 多个 count distinct

如果多个count distinct,去重的键是一样的,如对用户计算uv和去作弊uv,那么仍可按user_id去重后,根据是否作弊按0,1进行SUM。

如果去重的键是不一样的,那么多个count distinct 可以优化为多个group by再union all的方式。但这会扫描多次表,具体优化效果需根据具体情况测试确定。

2.2.4 使用脚本或udf

这个需要根据具体业务场景优化。如果不方便优化,可以降低 spark.sql.shuffle.partitions的值。

2.2.5 distriute by

distriute by 需要保证键比较均匀。同时,不能使用rand函数,否则shuffle fetch failed后,整个job会被kill

2.2.6 读取操作

读取一般不会倾斜。出现倾斜一般是上游文件数过少,下游处理的executor多。spark默认一个executor对应一个文件,这样会有大量executor空跑。这种情况可以使用 distriute by、repartition 等对文件重新分区。

相关推荐
Nile18 分钟前
解密Palantir系列一:3. Palantir 是谁
大数据·人工智能·ai
云天AI实战派19 分钟前
AI 智能体总是跑偏怎么办?ChatGPT/API/Agent 故障排查指南与全流程修复手册
大数据·人工智能·chatgpt·agent
逸Y 仙X28 分钟前
文章六:ElasticSearch 集群通信安全权限
java·大数据·服务器·elasticsearch·搜索引擎·全文检索
小脑斧12331 分钟前
AI Skills 全链路自动化运营实践:抖音热点、小红书种草与文生图一体化方案
大数据·人工智能·小红书·skills·自动化运营
白露与泡影36 分钟前
告别OOM焦虑:Flink 内存模型原理与诊断调优
大数据·flink
清辞8531 小时前
Ai应用——数据分析
大数据
冯RI375II694871 小时前
样品准备指南:LFGB认证检测送样要求详解
大数据
RingWu1 小时前
高并发三板斧-异步
分布式·微服务·架构
繁星星繁1 小时前
Git 入门之道:从版本流转到基础操作
大数据·git·elasticsearch
Komorebi_99992 小时前
Day3:监控、日志、限流、成本管控、版本灰度
大数据·运维·人工智能·大模型