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 等对文件重新分区。

相关推荐
AI_Auto41 分钟前
中小企业数字化转型指南 | 拆解中小企业数字化四大转型特征
大数据·人工智能·制造
资深低代码开发平台专家1 小时前
2026企业级AI编程平台厂推荐:行业趋势、评估维度与主流品牌对比解析
大数据·人工智能·ai编程
小白说大模型2 小时前
Spring AI 框架中集成 MCP 的完整指南:从服务端到客户端的全流程实践
大数据·数据库·人工智能·安全·spring·chatgpt·开源
一路向北finish3 小时前
《CentOS 7 搭建 Hadoop 3.3.6 分布式集群:NFS 共享方案完整实操》
linux·运维·hadoop·分布式·centos
HiDev_3 小时前
【非标自动化】2、认识元器件(液压泵和液压阀)
大数据·人工智能·自动化
ZhiMuZhiLing3 小时前
数据驱动的B2B客户画像:行业、规模、时间、地域维度解析
大数据·创业创新·流量运营
晓子文集3 小时前
Tushare接口文档:每日涨跌停价格(stk_limit)
大数据·数据库·金融数据·量化投资
IanSkunk3 小时前
眼视光设备全周期台账:从验收入库到使用效果数据化的管理闭环
大数据·网络·人工智能
拓人间精准客3 小时前
2025–2026 ToB 精准拓客实战手册:用“企业数据画像 + 动态筛选“击穿七大行业获客内卷
大数据·数据库·人工智能
天涯明月19933 小时前
Ray 架构解析——以动态任务图统一 AI 计算的分布式框架
大数据·人工智能·分布式·架构·ray