数据倾斜优化思路实践

数据倾斜,顾名思义,就是在计算过程中数据分散度不够,导致某个节点数据过于集中,从而导致任务执行效率大大降低。参照对比下MR的整体流程和ODPS,整体结合理解数据倾斜发生的几个生命周期的节点,如下图:可以分为Map、Reduce、Join三个阶段理解。

图片

在这里插入图片描述

Map端长尾
Map端是MR任务的开始,在Map端读取数据的时候,由于读入的数据文件大小分布不均匀,会导致一些Map instance的数据量很大,一些instance很小,造成了Map端长尾现象。一般情况下,Map端长尾现象较少,主要由以下两种原因导致:

Map端读入的文件大小不均匀,且小文件很多,导致当前Map端读取数据不均匀

Map端做聚合操作由于Map instance读取文件某个值较多引起长尾,主要指count(distinct)操作

方案
针对小文件和文件大小不均匀的情况,暂时没有特别好的方法,可以通过合并文件、文件切片大小等参数进行调优,即:set odps.sql.mapper.merge.limit.size = 64,set odps.sql.mapper.split.size = 256

针对第二种情况,采取distribute by rand()来打乱数据,使数据尽可能的分布均匀,如下:通过distribute by rand() 会让Map端分发后的数据重新随机进行一次分发。这种方式虽然平衡了instance处理的数据量,但是带来了Reduce端的资源紧张。具体可以增大Reduce端的instance个数,具体如下:set odps.sql.reducer.insatnce = 100;

select
t1.*
from
(
select
id,
name
from ods.cn_log_app_test01_pre_1d
where dt = ‘ d t ′ d i s t r i b u t e b y r a n d ( ) ) t 1 l e f t j o i n ( s e l e c t ∗ f r o m o d s . c n l o g a p p t e s t 0 2 p r e 1 d w h e r e d t = ′ {dt}' distribute by rand() )t1 left join ( select * from ods.cn_log_app_test02_pre_1d where dt = ' dtdistributebyrand())t1leftjoin(selectfromods.cnlogapptest02pre1dwheredt={dt}’
) t2
on t1.id = t2.id

Reduce端长尾
Reduce端主要负责的是对Map端输出的K-V形式的数据进行处理,比如常见的聚合操作,即count、sum、avg等,得到最终的聚合结果。Reduce端产生长尾现象的主要原因是key的分布不均匀导致。比如:一些instance处理的数据量很大,可能40min这个reduce task还没结束,有的instance处理的数据量很小,主要场景如下:(从上至下优先级为常见-> 少见)

在Join阶段经常发生的:空值很多,造成这么多的Null值被分发到同一个instance上

在Map端聚合操作的时候出现key值分布不均匀,从而导致Reduce端长尾

多个distinct出现在同一段SQL代码中,数据会被分发多次,不仅会造成数据膨胀,还会把长尾现象放大多倍

动态分区数过多可能造成小文件过多,从而引起Reduce端长尾

第一种场景方案

当存在很多Null值的时候,可以选择把空值数据单独拎出来,然后别的数据去做Join,最后再把空值数据union all上去即可。生产中,有些空值是具备业务含义的,比如:剩余还款字段,用户某个时间点已还清贷款,显然去掉空值数据是肯定不对的,所以需要具体情况具体分析

加随机数,打散,实际用的不多,第一种方式用的更高频

比如数据如下:
concat(name + ‘_’ + random)
乌克兰 -> 乌克兰_1
乌克兰 -> 乌克兰_2
乌克兰 -> 乌克兰_3

最终结果数据 res.split(‘_’)[0]再取回原数据即可
第二种场景方案

查看数据key的分布情况,对一些热点key进行单独计算,然后再union all回来,简单来说,就是两个任务单独处理,例如:select / + skewjoin (a(c0,c1)) /* from T0 a join T1 b on a.c0 = b.c0 and a.c1 = b.c1 and a.c2 = b.c2

第三种场景方案

ODPS对动态分区的处理是引入一个额外的一级reduce task,相同的目标分区交由一个(或者少量几个)reduce instance写入,避免小文件过多

第四种场景方案

遇到该情况,最好的办法就是通过其他方案例如:临时表、现有模型去计算去重的指标,避免使用distinct造成数据膨胀

Join长尾优化
Join是指将相同的数据分发到同一个instance上处理,如果某个key的value量级很大,处理时间很长,即称之为长尾。主要以下几个场景:

大表join小表
空值和热点值在reduce长尾场景中已经说过,见上文
场景一方案

t1表数据量级:9700w+ t2表量级:1000w+
SELECT /+mapjoin(t2)/
t1.*
,t2.f_guaname
,t2.f_guades
,t2.f_own
FROM (
SELECT *
FROM ods.ods_zdf_itf_company_mort
WHERE dt = ‘ b i z d a t e ′ A N D n v l ( f d e l e t e d , ′ 0 ′ ) = ′ 0 ′ ) t 1 L E F T J O I N ( S E L E C T f g u a n a m e , f g u a d e s , f o w n F R O M o d s . o d s z d f i t f c o m p a n y m o r t g u a W H E R E d t = ′ {bizdate}' AND nvl(f_deleted, '0') = '0' ) t1 LEFT JOIN ( SELECT f_guaname ,f_guades ,f_own FROM ods.ods_zdf_itf_company_mort_gua WHERE dt = ' bizdateANDnvl(fdeleted,0)=0)t1LEFTJOIN(SELECTfguaname,fguades,fownFROMods.odszdfitfcompanymortguaWHEREdt={bizdate}’
AND nvl(f_deleted, ‘0’) = ‘0’
) t2
ON t1.f_morreg_id = t2.f_morreg_id
ODPS高频的长尾参数配置
set odps.sql.groupby.skewindata=true/false

row_number()优化【不常用】
分组过程中可能某个key的数据量太大,会造成倾斜的,那么自己搞个随机列,根据key + random分组,那么这个热点key的数据其实就打散了,那么再求出topN,其实这批次topN就已经是一定条件下的好马了,内层循环已经避免了数据倾斜,外层直接根据key全局分组,相当于这批好马里再挑好马。

select cate_id
,property_id
,value_id
from
(select cate_id
,property_id
,value_id
,row_number() over(partition by cate_id order by property_id asc,value_id asc) as rn
from
(select cate_id
,property_id
,value_id
from
(select cate_id
,property_id
,value_id
,row_number() over(partition by cate_id,sec_part order by property_id asc,value_id asc) as rn
from
(select cate_id
,property_id
,value_id
,ceil(M*rand())%P as sec_part
from one_plat.ads_tb_sycm_cate_xx
where ds = ‘${bizdate}’
) s
) p
where rn <= N
) part
) a
where rn <= N
常见资源配置参数
设置Map Task每个instance的cpu数,默认在[50-800]之间,一般不会调
set odps.sql.mapper.cpu=100;

设定Map Task每个Instance的Memory大小,单位M,默认1024M
set odps.sql.mapper.memory=1024;

设定一个Map的最大数据输入量
set odps.sql.mapper.split.size=256
[最好不要降低这个阈值,因为每个map task的instance时间是减少了,但是小文件多了,合并时间翻倍,得不偿失]

设定Join Task的Instance数量,默认为-1,在[0,2000]之间调整
set odps.sql.joiner.instances=-1;
场景:每个Join Instance处理的数据量比较大,耗时较长,没有发生长尾,可以考虑增大使用这个参数。

扩大string字符串的大小,这个场景是之前字符串中存储多条json的时候,多的存储几十万条,超出string默认大小,只能修改string大小,需要注意的是要不断调节,有OOM的风险
set odps.sql.cfile2.field.maxsize=16384;
总结
尽量不要通过设置参数的方式进行优化,首先要看能否从业务上或者算法上减少数据和其他方式进行优化

设置参数的话,要首先确定是Map、Reduce、Join哪个阶段的任务时间长,从而设置对应的参数

在没有出现数据倾斜的情况下,如果通过设置Cpu参数(含Memory参数)和设置Instance个数两种方式都能调优的话,最好是先设置Instance个数。因为如果Cpu/Memory参数设置不合理,执行任务的机器满足不了参数的要求,要重新找机器的,这样反而会影响效率

Instance的个数设置,有个简单的方法是二分法。先设置个很大的,如果不能满足要求,那么就继续增大,如果满足了要求,就折半降低参数大小,最终找到一个合适的值

如果面试中问到hivesql的优化,可以侧重数据倾斜做不同场景的优化分析,尽量避免按照网上的优化套路回答,往往效果不佳,毕竟面试官能搜到的答案,大概率不是他想看到的答案,突出有自己的思考且真正的有所应用才是最重要的,不然就会出现自己觉得答的很不错最后却没了结果。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/385254.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Stable Diffusion绘画 | 新手必备知识点(一)

模型 模型分为 大模型 Checkpoint 、 Lora模型 以及 其他模型。 大模型是生成图片的基石&#xff0c;选择怎样的大模型&#xff0c;会直接影响图片最终生成的风格。 大模型 大模型又分为 普通模型 以及 SDXL模型&#xff0c;包括&#xff1a; 真实风二次元2.5D 普通模型&…

[C#]调用本地摄像头录制视频并保存

AForge.NET是一个基于C#框架设计的开源计算机视觉和人工智能库&#xff0c;专为开发者和研究者设计。它提供了丰富的图像处理和视频处理算法、机器学习和神经网络模型&#xff0c;具有高效、易用、稳定等特点。AForge库由多个组件模块组成&#xff0c;包括AForge.Imaging&#…

Datawhale AI 夏令营——AI+逻辑推理——Task1

# Datawhale AI 夏令营 夏令营手册&#xff1a;从零入门 AI 逻辑推理 比赛&#xff1a;第二届世界科学智能大赛逻辑推理赛道&#xff1a;复杂推理能力评估 代码运行平台&#xff1a;魔搭社区 比赛任务 本次比赛提供基于自然语言的逻辑推理问题&#xff0c;涉及多样的场景&…

大数据——Hive原理

摘要 Apache Hive 是一个基于 Hadoop 分布式文件系统 (HDFS) 的数据仓库软件项目&#xff0c;专为存储和处理大规模数据集而设计。它提供类似 SQL 的查询语言 HiveQL&#xff0c;使用户能够轻松编写复杂的查询和分析任务&#xff0c;而无需深入了解 Hadoop 的底层实现。 Hive…

Android TabLayout的简单用法

TabLayout 注意这里添加tab&#xff0c;使用binding.tabLayout.newTab()进行创建 private fun initTabs() {val tab binding.tabLayout.newTab()tab.text "模板库"binding.tabLayout.addTab(tab)binding.tabLayout.addOnTabSelectedListener(object : TabLayout.On…

day3 测试基础知识

1. 你认为性能测试的目的是什么&#xff1f;做好性能测试的工作的关键是什么&#xff1f; 性能测试工作的目的是检查系统是否满足在需求说明书中规定的性能&#xff0c;性能测试常常需要和强度测试结合起来&#xff0c;并常常要求同时进行软件和硬件的检测。 性能测试主要的关…

MySQL中实现动态表单中JSON元素精准匹配的方法

目录 前言 一、动态表单技术 1、包含的主要信息 2、元素属性设置 3、表单内容 二、表单数据存储和查询 1、数据存储 2、数据的查询 3、在5.7版本中进行JSON检索 4、8.0后的优化查询 三、总结 前言 在很多有工作流设置的地方、比如需要在不同的流程中&#xff0c;需要…

【初阶数据结构篇】顺序表的实现(赋源码)

文章目录 本篇代码位置顺序表和链表1.线性表2.顺序表2.1 概念与结构2.2分类2.2.1 静态顺序表2.2.2 动态顺序表 2.3 动态顺序表的实现2.3.1动态顺序表的初始化和销毁及打印2.3.2动态顺序表的插入动态顺序表的尾插动态顺序表的头插动态顺序表的在指定位置插入数据 2.3.3动态顺序表…

html+css 实现单选按钮动画(input radio按钮)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享htmlcss 绚丽效果&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 文…

【第二天】计算机网络 HTTP请求报文和响应报文是什么样的 HTTP请求方式有哪些 GET请求和POST请求的区别

HTTP请求报文和响应报文是什么样的&#xff1f; 我去&#xff0c;以前都没怎么研究过这个。 客户端发送一个请求给服务器&#xff0c;服务器根据请求报文中的信息进行处理&#xff0c;并将处理结果放到响应报文中返回给客户端。 URL HTTP使用URL (Uniform Resource Locator&…

OriginPro 2024b (学习版) 绘制3D坐标下 边际直方图

OriginPro 2024b (学习版) 绘制3D坐标下 边际直方图 时间 2024年7月27日 1.导入数据 需要3列数据&#xff0c;分别作为x,y,z, 其中z值随便设置。快速设置z值的方法&#xff1a;在第4行“F(x)”输入1&#xff0c;这一列的值全设置为1了。 设置x,y,z的方法如下&#xff1a;点击…

WHAT - 一个 Github 仓库的 License 如何解读

目录 一、背景二、解读许可证说明的作用常见的开源许可证类型使用他人代码仓库时需要注意的事项结论 实践作为开发者1. 选择许可证类型2. 在 README 文件中编写许可证信息 作为使用者1. 确定权限2. 了解和遵守条款 总结 一、背景 我们经常在一些 Github 仓库里看到 License 部…

如何知道一个字段在selenium中是否可编辑?

这篇文章将检查我们如何使用Java检查selenium webdriver中的字段是否可编辑。 我们如何知道我们是否可以编辑字段&#xff1f;“readonly”属性控制字段的可编辑性。如果元素上存在“readonly”属性&#xff0c;则无法编辑或操作该元素或字段。 因此&#xff0c;如果我们找到一…

【每日一篇】使用图神经网络进行交通速度预测的上下文感知知识图谱框架【为了自己方便读论文】

Context-aware knowledge graph framework for traffic speed forecasting using graph neural network 论文链接&#xff1a; https://arxiv.org/abs/2407.17703 翻译&#xff1a; 摘要 人类流动在空间和时间上受到城市环境的密切影响&#xff0c;构成了理解交通系统的重…

electron TodoList网页应用打包成linux deb、AppImage应用

这里用的是windows的wsl的ubuntu环境 electron应用打包linux应用需要linux下打包&#xff0c;这里用windows的wsl的ubuntu环境进行操作 1&#xff09;linux ubuntu安装nodejs、electron 安装nodejs&#xff1a; sudo apt update sudo apt upgrade ##快捷安装 curl -fsSL http…

7-23学习笔记

一、异常 即程序中一些程序处理不了的特殊情况 Exception 能被程序本身处理( try-catch )&#xff0c; Error 是无法处理的(只能尽量避免)。 1、异常类 Exception 见过的异常 NullPointerException ArrayIndexoutOfBoundException等 String strnull;System.out.println(st…

《python程序语言设计》第6章14题 估算派值 类似莱布尼茨函数。但是我看不明白

这个题提供的公式我没看明白&#xff0c;后来在网上找到了莱布尼茨函数 c 0 for i in range(1, 902, 100):a (-1) ** (i 1)b 2 * i - 1c a / bprint(i, round(4 / c, 3))结果 #按题里的信息&#xff0c;但是结果不对&#xff0c;莱布尼茨函数到底怎么算呀。

Docker学习与实战

一、Docker安装 移除旧版本docker sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-engine配置docker yum源 sudo yum install -y yum-utils配置阿里云docker仓库 sudo y…

学习记录:ESP32控制舵机 FREERTOS BLE

控制舵机 PWM信号 PWM信号是一种周期性变化的方波信号&#xff0c;它有两个关键参数&#xff1a; 周期&#xff08;Period&#xff09;&#xff1a;一个完整的PWM信号的时间长度&#xff0c;通常用秒&#xff08;s&#xff09;或毫秒&#xff08;ms&#xff09;表示。占空比…

前端开发:HTML与CSS

文章目录 前言1.1、CS架构和BS架构1.2、网页构成 HTML1.web开发1.1、最简单的web应用程序1.2、HTTP协议1.2.1 、简介1.2.2、 http协议特性1.3.3、http请求协议与响应协议 2.HTML概述3.HTML标准结构4.标签的语法5.基本标签6.超链接标签6.1、超链接基本使用6.2、锚点 7.img标签8.…