9Hive数据倾斜
这里写目录标题
- 数据倾斜问题剖析
- 数据倾斜解决方案
- 1. 空值引发的数据倾斜
- 2. 不同数据类型引发的数据倾斜
- 3. 不可拆分大文件引发的数据倾斜
- 4. 数据膨胀引发的数据倾斜
- 5. 表连接时引发的数据倾斜
- 6. 确实无法减少数据量引发的数据倾斜
- 总结
数据倾斜问题剖析
数据倾斜是分布式系统不可避免的问题,任何分布式系统都有几率发生数据倾斜,但有些小伙伴在平时工作中感知不是很明显,这里要注意本篇文章的标题—“千亿级数据”,为什么说千亿级,因为如果一个任务的数据量只有几百万,它即使发生了数据倾斜,所有数据都跑到一台机器去执行,对于几百万的数据量,一台机器执行起来还是毫无压力的,这时数据倾斜对我们感知不大,只有数据达到一个量级时,一台机器应付不了这么多的数据,这时如果发生数据倾斜,那么最后就很难算出结果。
所以就需要我们对数据倾斜的问题进行优化,尽量避免或减轻数据倾斜带来的影响。
在解决数据倾斜问题之前,还要再提一句:没有瓶颈时谈论优化,都是自寻烦恼。
大家想想,在map和reduce两个阶段中,最容易出现数据倾斜的就是reduce阶段,因为map到reduce会经过shuffle阶段,在shuffle中默认会按照key进行hash,如果相同的key过多,那么hash的结果就是大量相同的key进入到同一个reduce中,导致数据倾斜。
那么有没有可能在map阶段就发生数据倾斜呢,是有这种可能的。
一个任务中,数据文件在进入map阶段之前会进行切分,默认是128M一个数据块,但是如果当对文件使用GZIP压缩等不支持文件分割操作的压缩方式时,MR任务读取压缩后的文件时,是对它切分不了的,该压缩文件只会被一个任务所读取,如果有一个超大的不可切分的压缩文件被一个map读取时,就会发生map阶段的数据倾斜。
所以,从本质上来说,发生数据倾斜的原因有两种:一是任务中需要处理大量相同的key的数据。二是任务读取不可分割的大文件。
数据倾斜解决方案
MapReduce和Spark中的数据倾斜解决方案原理都是类似的,以下讨论Hive使用MapReduce引擎引发的数据倾斜,Spark数据倾斜也可以此为参照。
1. 空值引发的数据倾斜
实际业务中有些大量的null值或者一些无意义的数据参与到计算作业中,表中有大量的null值,如果表之间进行join操作,就会有shuffle产生,这样所有的null值都会被分配到一个reduce中,必然产生数据倾斜。
之前有小伙伴问,如果A、B两表join操作,假如A表中需要join的字段为null,但是B表中需要join的字段不为null,这两个字段根本就join不上啊,为什么还会放到一个reduce中呢?
这里我们需要明确一个概念,数据放到同一个reduce中的原因不是因为字段能不能join上,而是因为shuffle阶段的hash操作,只要key的hash结果是一样的,它们就会被拉到同一个reduce中。
解决方案:
第一种:可以直接不让null值参与join操作,即不让null值有shuffle阶段
SELECT *
FROM log aJOIN users bON a.user_id IS NOT NULLAND a.user_id = b.user_id
UNION ALL
SELECT *
FROM log a
WHERE a.user_id IS NULL;
第二种:因为null值参与shuffle时的hash结果是一样的,那么我们可以给null值随机赋值,这样它们的hash结果就不一样,就会进到不同的reduce中:
SELECT *
FROM log aLEFT JOIN users b ON CASE WHEN a.user_id IS NULL THEN concat('hive_', rand())ELSE a.user_idEND = b.user_id;
2. 不同数据类型引发的数据倾斜
对于两个表join,表a中需要join的字段key为int,表b中key字段既有string类型也有int类型。当按照key进行两个表的join操作时,默认的Hash操作会按int型的id来进行分配,这样所有的string类型都被分配成同一个id,结果就是所有的string类型的字段进入到一个reduce中,引发数据倾斜。
解决方案:
如果key字段既有string类型也有int类型,默认的hash就都会按int类型来分配,那我们直接把int类型都转为string就好了,这样key字段都为string,hash时就按照string类型分配了:
SELECT *
FROM users aLEFT JOIN logs b ON a.usr_id = CAST(b.user_id AS string);
3. 不可拆分大文件引发的数据倾斜
当集群的数据量增长到一定规模,有些数据需要归档或者转储,这时候往往会对数据进行压缩;当对文件使用GZIP压缩等不支持文件分割操作的压缩方式,在日后有作业涉及读取压缩后的文件时,该压缩文件只会被一个任务所读取。如果该压缩文件很大,则处理该文件的Map需要花费的时间会远多于读取普通文件的Map时间,该Map任务会成为作业运行的瓶颈。这种情况也就是Map读取文件的数据倾斜。
解决方案:
这种数据倾斜问题没有什么好的解决方案,只能将使用GZIP压缩等不支持文件分割的文件转为bzip和zip等支持文件分割的压缩方式。
所以,我们在对文件进行压缩时,为避免因不可拆分大文件而引发数据读取的倾斜,在数据压缩的时候可以采用bzip2和Zip等支持文件分割的压缩算法。
4. 数据膨胀引发的数据倾斜
在多维聚合计算时,如果进行分组聚合的字段过多,如下:
select a,b,c,count(1)from log group by a,b,c with rollup;
注:对于最后的with rollup关键字不知道大家用过没,with rollup是用来在分组统计数据的基础上再进行统计汇总,即用来得到group by的汇总信息。
如果上面的log表的数据量很大,并且Map端的聚合不能很好地起到数据压缩的情况下,会导致Map端产出的数据急速膨胀,这种情况容易导致作业内存溢出的异常。如果log表含有数据倾斜key,会加剧Shuffle过程的数据倾斜。
解决方案:
可以拆分上面的sql,将with rollup拆分成如下几个sql:
SELECT a, b, c, COUNT(1)
FROM log
GROUP BY a, b, c;
SELECT a, b, NULL, COUNT(1)
FROM log
GROUP BY a, b;
SELECT a, NULL, NULL, COUNT(1)
FROM log
GROUP BY a;
SELECT NULL, NULL, NULL, COUNT(1)
FROM log;
但是,上面这种方式不太好,因为现在是对3个字段进行分组聚合,那如果是5个或者10个字段呢,那么需要拆解的SQL语句会更多。
在Hive中可以通过参数 hive.new.job.grouping.set.cardinality 配置的方式自动控制作业的拆解,该参数默认值是30。表示针对grouping sets/rollups/cubes这类多维聚合的操作,如果最后拆解的键组合大于该值,会启用新的任务去处理大于该值之外的组合。如果在处理数据时,某个分组聚合的列有较大的倾斜,可以适当调小该值。
5. 表连接时引发的数据倾斜
两表进行普通的repartition join时,如果表连接的键存在倾斜,那么在 Shuffle 阶段必然会引起数据倾斜。
解决方案:
通常做法是将倾斜的数据存到分布式缓存中,分发到各个 Map任务所在节点。在Map阶段完成join操作,即MapJoin,这避免了 Shuffle,从而避免了数据倾斜。
MapJoin是Hive的一种优化操作,其适用于小表JOIN大表的场景,由于表的JOIN操作是在Map端且在内存进行的,所以其并不需要启动Reduce任务也就不需要经过shuffle阶段,从而能在一定程度上节省资源提高JOIN效率。
在Hive 0.11版本之前,如果想在Map阶段完成join操作,必须使用MAPJOIN来标记显示地启动该优化操作,由于其需要将小表加载进内存所以要注意小表的大小。
如将a表放到Map端内存中执行,在Hive 0.11版本之前需要这样写:
select /* +mapjoin(a) */ a.id , a.name, b.age
from a join b
on a.id = b.id;
如果想将多个表放到Map端内存中,只需在mapjoin()中写多个表名称即可,用逗号分隔,如将a表和c表放到Map端内存中,则 /* +mapjoin(a,c) */ 。
在Hive 0.11版本及之后,Hive默认启动该优化,也就是不在需要显示的使用MAPJOIN标记,其会在必要的时候触发该优化操作将普通JOIN转换成MapJoin,可以通过以下两个属性来设置该优化的触发时机:
hive.auto.convert.join=true 默认值为true,自动开启MAPJOIN优化。
hive.mapjoin.smalltable.filesize=2500000 默认值为2500000(25M),通过配置该属性来确定使用该优化的表的大小,如果表的大小小于此值就会被加载进内存中。
注意:使用默认启动该优化的方式如果出现莫名其妙的BUG(比如MAPJOIN并不起作用),就将以下两个属性置为fase手动使用MAPJOIN标记来启动该优化:
hive.auto.convert.join=false (关闭自动MAPJOIN转换操作)
hive.ignore.mapjoin.hint=false (不忽略MAPJOIN标记)
再提一句:将表放到Map端内存时,如果节点的内存很大,但还是出现内存溢出的情况,我们可以通过这个参数 mapreduce.map.memory.mb 调节Map端内存的大小。
6. 确实无法减少数据量引发的数据倾斜
在一些操作中,我们没有办法减少数据量,如在使用 collect_list 函数时:
select s_age,collect_list(s_score) list_score
from student
group by s_age
collect_list:将分组中的某列转为一个数组返回。
在上述sql中,s_age有数据倾斜,但如果数据量大到一定的数量,会导致处理倾斜的Reduce任务产生内存溢出的异常。
collect_list输出一个数组,中间结果会放到内存中,所以如果collect_list聚合太多数据,会导致内存溢出。
有小伙伴说这是 group by 分组引起的数据倾斜,可以开启hive.groupby.skewindata参数来优化。我们接下来分析下:
开启该配置会将作业拆解成两个作业,第一个作业会尽可能将Map的数据平均分配到Reduce阶段,并在这个阶段实现数据的预聚合,以减少第二个作业处理的数据量;第二个作业在第一个作业处理的数据基础上进行结果的聚合。
hive.groupby.skewindata的核心作用在于生成的第一个作业能够有效减少数量。但是对于collect_list这类要求全量操作所有数据的中间结果的函数来说,明显起不到作用,反而因为引入新的作业增加了磁盘和网络I/O的负担,而导致性能变得更为低下。
解决方案:
这类问题最直接的方式就是调整reduce所执行的内存大小。
调整reduce的内存大小使用mapreduce.reduce.memory.mb这个配置。
总结
通过上面的内容我们发现,shuffle阶段堪称性能的杀手,为什么这么说,一方面shuffle阶段是最容易引起数据倾斜的;另一方面shuffle的过程中会产生大量的磁盘I/O、网络I/O 以及压缩、解压缩、序列化和反序列化等。这些操作都是严重影响性能的。
所以围绕shuffle和数据倾斜有很多的调优点:Mapper 端的Buffer 设置为多大? Buffer 设置得大,可提升性能,减少磁盘I/O ,但 是对内存有要求,对GC 有压力; Buffer 设置得小,可能不占用那么多内存, 但是可 能频繁的磁盘I/O 、频繁的网络I/O 。
相关文章:
9Hive数据倾斜
这里写目录标题 数据倾斜问题剖析数据倾斜解决方案1. 空值引发的数据倾斜2. 不同数据类型引发的数据倾斜3. 不可拆分大文件引发的数据倾斜4. 数据膨胀引发的数据倾斜5. 表连接时引发的数据倾斜6. 确实无法减少数据量引发的数据倾斜 总结 数据倾斜问题剖析 数据倾斜是分布式系统…...

【大数据】机器学习 -----关于data.csv数据集分析案例
打开表 import pandas as pd df2 pd.read_csv("data.csv",encoding"gbk") df2.head()查看数据属性(列标题,表形状,类型,行标题,值) print("列标题:",df2.columns)Data…...
深入解析 C++ 类型转换
简介 C 类型转换是开发者必须掌握的重要技能之一, 无论是处理隐式转换还是显式转换, 理解其背后的机制与用法至关重要. 本篇博客旨在从基础到高级全面解析 C 的类型转换, 包括实际开发中的应用场景和性能分析. 自动转换 隐式类型转换 编译器可以在无需明确指示的情况下, 将一…...
C++ union 联合(八股总结)
union(联合体)允许在同一内存位置上存储不同的数据类型,所有成员共享相同的内存空间。 内存布局 由于联合体的所有成员都共享同一块内存,因此联合体的大小是其最大成员的大小。联合体的实际大小取决于其最大成员的类型和对齐要求…...
聊聊AI Agent
什么是AI Agent? AI Agent指的是一种使用人工智能技术的自主实体,它能够感知环境、做出决策,并采取行动以实现特定目标。AI Agent的核心思想是它能够独立运作,基于输入信息做出有根据的决策,并通过学习算法不断提高自…...

scala代码打包配置(maven)
目录 mavenpom.xml打包配置项(非完整版,仅含打包的内容< build>)pom.xml完整示例(需要修改参数)效果说明 maven 最主要的方式还是maven进行打包,也好进行配置项的管理 以下为pom文件(不要…...

慧集通(DataLinkX)iPaaS集成平台-业务建模之业务对象(二)
3.UI模板 当我们选择一条已经建好的业务对象点击功能按钮【UI模板】进入该业务对象的UI显示配置界面。 右边填写的是UI模板的编码以及对应名称;菜单界面配置以业务对象UI模板编码获取显示界面。 3.1【列表-按钮】 展示的对应业务对象界面的功能按钮配置࿱…...
C++使用minio-cpp库在minio中创建bucket
直接看代码 #include <iostream> #include <string>#include "miniocpp/client.h"int main() {minio::s3::BaseUrl baseUrl("base url");minio::creds::StaticProvider staticProvider("access key", "secret key");mini…...
【大模型】大语言模型的数据准备:构建高质量训练数据的关键指南
大语言模型的数据准备:构建高质量训练数据的关键指南 大语言模型(LLM, Large Language Model)的训练离不开高质量的数据,而数据准备是模型性能的基石。无论是预训练还是微调,数据的选择、清洗和标注都会直接影响模型的…...

【解决】okhttp的java.lang.IllegalStateException: closed错误
问题 Android 使用OKHttp进行后端通信,后端处理结果,反馈给前端的responseBody中其实有值,但是一直报异常,后来才发现主要是OkHttp请求回调中response.body().string()只能有效调用一次,而我使用了两次: 解…...

TCP-IP详解卷 TCP的超时与重传
TCP-IP详解卷1-21:TCP的超时与重传(Timeout and Retransmission) 一:介绍 1: 与数据链路层的ARQ协议相类似,TCP使用超时重发的重传机制。 即:TCP每发送一个报文段,就对此报文段设置…...
Linux服务器查看【可用端口号连接】的命令和方式【netstat,ss,lsof】
Linux服务器查看可用连接的端口号的命令和方式 前言:1. 使用netstat命令(netstat命令详解及使用指南)一、什么是netstat二、基本使用方法与参数解释三、输出结果字段含义:四、查找可用于SSH连接的端口示例五、部分高级用法&#x…...

【WPS】【WORDEXCEL】【VB】实现微软WORD自动更正的效果
1. 代码规范方面 添加 Option Explicit:强制要求显式声明所有变量,这样可以避免因变量名拼写错误等情况而出现难以排查的逻辑错误,提高代码的健壮性。使用 On Error GoTo 进行错误处理:通过设置错误处理机制,当代码执行…...
Attention计算中的各个矩阵的维度都是如何一步步变化的?
在Transformer模型中,各个矩阵的维度变化是一个关键的过程,涉及到输入、编码器、解码器和输出等多个阶段。以下是详细的维度变化过程: 输入阶段 输入序列:假设输入序列的长度为seq_len,每个单词或标记通过词嵌入&…...

【数模学习笔记】插值算法和拟合算法
声明:以下笔记中的图片以及内容 均整理自“数学建模学习交流”清风老师的课程资料,仅用作学习交流使用 文章目录 插值算法定义三个类型插值举例插值多项式分段插值三角插值 一般插值多项式原理拉格朗日插值法龙格现象分段线性插值 牛顿插值法 Hermite埃尔…...
探索 C++ 与 LibUSB:开启 USB 设备交互的奇幻之旅
一、引言 在当今数字化时代,USB(通用串行总线)设备无处不在,从常见的 U 盘、鼠标、键盘,到复杂的工业数据采集设备、医疗监测仪器等,它们以方便快捷的插拔式连接,为人们的生活和工作带来了极大…...

二、模型训练与优化(4):模型优化-实操
下面我将以 MNIST 手写数字识别模型为例,从 剪枝 (Pruning) 和 量化 (Quantization) 两个常用方法出发,提供一套可实际动手操作的模型优化流程。此示例基于 TensorFlow/Keras 环境,示范如何先训练一个基础模型,然后对其进行剪枝和…...
3D可视化产品定制,应用于哪些行业领域?
3D可视化定制服务已广泛渗透至众多行业领域,包括汽车、家居、时尚鞋服、珠宝配饰以及数码电器等: 汽车行业: 借助Web全景技术与3D模型,我们高保真地再现了汽车外观,为用户带来沉浸式的车型浏览体验。用户可在展示界面自…...

Avalonia 入门笔记(零):概述
Avalonia 是一个基于 .NET 和 Skia 的开源、跨平台 UI 框架,支持 Windows、Linux、macOS、iOS、Android 和 WebAssembly。Skia 是一个基于 C 的开源 2D 渲染引擎,Avalonia 通过 Skia 自绘 UI 控件,保证在全平台具有一致的观感 基于 .NET 的跨…...

Unity TextMesh Pro入门
概述 TextMesh Pro是Unity提供的一组工具,用于创建2D和3D文本。与Unity的UI文本和Text Mesh系统相比,TextMesh Pro提供了更好的文本格式控制和布局管理功能。 本文介绍了TMP_Text组件和Tmp字体资产(如何创建字体资产和如何解决缺字问题),还有一些高级功…...

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...

JavaSec-RCE
简介 RCE(Remote Code Execution),可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景:Groovy代码注入 Groovy是一种基于JVM的动态语言,语法简洁,支持闭包、动态类型和Java互操作性,…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例
使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
Qt Http Server模块功能及架构
Qt Http Server 是 Qt 6.0 中引入的一个新模块,它提供了一个轻量级的 HTTP 服务器实现,主要用于构建基于 HTTP 的应用程序和服务。 功能介绍: 主要功能 HTTP服务器功能: 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计
随着大语言模型(LLM)参数规模的增长,推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长,而KV缓存的内存消耗可能高达数十GB(例如Llama2-7B处理100K token时需50GB内存&a…...

如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...

【数据分析】R版IntelliGenes用于生物标志物发现的可解释机器学习
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍流程步骤1. 输入数据2. 特征选择3. 模型训练4. I-Genes 评分计算5. 输出结果 IntelliGenesR 安装包1. 特征选择2. 模型训练和评估3. I-Genes 评分计…...