Vol.01 实际案例-数据倾斜

我的观点:数仓工程师的理论,需要在不断的实践中得到检验,最终才能沉淀为自己的知识与能力

作为第一篇关于数仓的文章,正好结合最近实际案例中的一次数据倾斜问题,来聊聊排查思路与修复方案

事发场景

在本周某天早上,意外收到某张宽表的报错(已跑了一个多月且近期没有任何修改)

当时还挺紧张的,因为本周刚用这张表给管理层支持了核心看板

也来不及多想了,以解决问题优先

解决步骤

先看看系统提供的报错信息

错误原因:Executor OOM

解决方案:Executor内存不足(堆内存溢出),请扩大内存参数重跑

参数建议:set spark.executor.memory=12g

由于不是Driver OOM,可以暂不考虑广播数据大小超过阈值的问题

猜测大概率是发生数据倾斜,导致某(几)个Executor的需处理的数据量过大

直接尝试调大内存后执行

万一成功了岂不是省时间了?

但与此同时,我们还是需要排查问题,因为加参数只是一种在业务SQL调优达到瓶颈后锦上添花的手段

毕竟有相当大的概率,加了参数后也是会执行失败

而且如果是Executor数据倾斜,调大参数后任务报错所花费的时间会更长

打开Spark UI查看卡点

3.1. 点击上方Tab里的「Stages」,可以看到具体失败在哪个Stage

3.2. 点击上方Tab里的「SQL」,通过WholeStageCodegen (8) 往上查找对应表名等信息,以判断是SQL的哪个位置

3.3. 点击「Description」对应的链接,查看具体的WholeStageCodegen (X)

最终定位到具体的SQL

已根据实际的复杂SQL处理成好理解的简单SQL

SQL 复制代码
select a.*
from a
left join b
    on  a.id = b.id
    and nvl(a.id, '-1') != '-1'
where a.日期分区 = 'XXXX'
  and b.id is not null

由于一些业务场景,该「id字段」实际不存在对应的业务值,我们以-1进行填充,且事先也知道-1的量远超其他值

我个人写SQL的时候会以这样的方式,尝试去避免倾斜:希望-1不参与关联,预期的效果如下

sql 复制代码
-- 非-1的参与关联
select a.*
from a
left join b    -- 非日期分区表
    on a.id = b.id
where a.日期分区 = 'XXXX'
  and a.id != '-1'
  and b.id is not null

union all

-- -1单独处理并合并
select a.*
from a
where a.日期分区 = 'XXXX'
  and a.id = '-1'
;

但根据最终的情况与结果看,-1的那些记录也参与了关联时的分组操作,不然也不会存在倾斜现象

经过了一开始的改参数调内存、再到仔细翻阅SQL,最终是将SQL从改成了第二段后成功执行

事后复盘

为什么近期未修改过的SQL,会莫名其妙发生倾斜了呢?

还记得排查问题期间,倾斜的那块UI执行计划上写的是ShuffledHashJoin吗?

我打开了前几天任务的执行计划,发现这块的关联操作都是广播BroadcastHashJoin

瞬间就明白了,看来是小表的数据量近期慢慢变大,超过了系统配置的广播阈值,因此从 BroadcastHashJoin 变成了 ShuffledHashJoin

那!= '-1' 写在on里,其执行计划是什么样的呢?

我将「解决步骤」中「4. 最终定位到具体的SQL」中,两段SQL的物理执行计划进行比较

倾斜SQL的核心执行计划
非倾斜SQL的核心执行计划

根据执行计划看下来,on里虽然写了左表的条件过滤,希望其不参与关联,但对应的值还是会参与hashpartitioning

后续解决

排查一下这个核心链路上,是否还有其他类似的id关联(即存在空字符串、-1、0、null的情况)

如有,看是否需要使用**id != '-1' union all id = '-1'** 的快速方式优先解决

由于这个条链路是新上的(服务于核心看板),加上自己也疏忽未配置相应的电话告警(我是正好凌晨醒了一下,看了眼手机);需要配置一下信息

随笔感慨

凌晨调度的SQL,截止成功执行的那一刻前,你都不知道会不会发生什么事情意外的事情

至于面试时常被问到的数据倾斜问题,市面上的解决方案大部分数仓工程师应该都能口述几个

  1. 倾斜的Key单独拎出来进行 union all(像我这样)
  2. 找一个其他分散的字段打散后再处理
  3. 能走广播的话走广播
  4. ...

但真到了实战中,我觉得下述内容才是数仓工程师需要不断打磨、保持的

  • 如何在复杂的SQL代码中快速定位到具体的问题点

  • 找到长期有效的解决办法

  • 有强烈的责任心、夜间保障意识

数仓就是这样

相关推荐
宸津-代码粉碎机1 小时前
AI攻防战升级!基于Spring AI构建Java应用自动免疫安全体系
java·大数据·开发语言·人工智能·python·安全·spring
博、、2 小时前
从零构建智慧场馆解决方案:架构设计与开发实践
大数据·运维
AI行业说2 小时前
誉财自动化YC-18-M8045实测:服装自动化vs人工缝制产能成本对比
大数据·人工智能·自动化·智能模板机
2601_963749102 小时前
越华环保集团数字化污水治理:端边云采集架构与平台对接实现
java·大数据·架构
爱吃火鸡面呀2 小时前
MySQL DQL 子查询详解:从标量、列、行到表子查询的完整实战
大数据·数据库·mysql
AI科技先锋报3 小时前
AI数据资产管理平台全景洞察:从治理基座到智能体应用
大数据·人工智能
华奥系科技4 小时前
银发经济浪潮下,智慧养老该如何落地生根
大数据·人工智能
百胜软件@百胜软件4 小时前
百胜软件入选“828精选AI解决方案图谱”,胜券AI助力零售品牌构建专属智能体
大数据·人工智能·零售
大大大大晴天5 小时前
把湖仓一体放进 K8s:Iceberg、Hudi、Paimon 如何重塑云原生大数据架构
大数据
阿里云大数据AI技术5 小时前
从“找得到”到“找得准”:用 Hologres 构建智能达人圈选系统
大数据·人工智能