DataSkew 数据倾斜
date: 2020-04-21 19:38:00
updated: 2020-04-24 10:26:00
DataSkew 数据倾斜
1. Hive 里的数据倾斜
1.1 null值 空值
尽量提前过滤,或者把无效值替换成随机字符串,比如 if(a is null or trim(a) = "" or trim(a) = "NULL", rand(1)+""),由于是无效值所以不影响最终的取数,但是因为把关联字段打散了,所以就不会把所有的key发送到同一个reduce上,但是需要控制rand(1)的数据范围,小数点位数过多会导致分配的reduce太多,也会影响最终效率。
打散key的方式同样适用于MapReduce和Spark。
1.2 小文件倾斜
这一点在 Hive 里主要表现在模型汇总程度越高,数据量越小,如果再带有分区,那么在HDFS里就会有很多小文件。HDFS的文件元信息,包括位置、大小、分块信息都保存在NameNode的内存中,文件越多占的内存越大,所以读取小文件就会消耗时间。还有一种产生的可能是MapReduce的reduce数量增加,也会增加输出结果文件的数量,从而导致小文件过多。
最后这种情况主要针对的是 MapReduce。当然Hive也可以通过配置项来尽可能减少reduce输出的小文件。
解决方法有两种:
- map输入端的小文件合并
-- 每个Map最大输入大小,决定合并后的文件数
set mapred.max.split.size=256000000; **常见**
-- 一个节点上split的至少的大小 ,决定了多个data node上的文件是否需要合并
set mapred.min.split.size.per.node=100000000;
-- 一个交换机下split的至少的大小,决定了多个交换机上的文件是否需要合并
set mapred.min.split.size.per.rack=100000000;
-- 执行Map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat; **常见**
- reduce输出端的小文件合并
hive.merge.mapfiles=True True时在map输出后合并文件,默认true
hive.merge.mapredfiles=True True时在reduce输出后合并文件,默认false
hive.merge.size.per.task 合并后每个文件的大小,默认256000000
hive.merge.smallfiles.avgsize 当输出文件平均大小小于设定值时,并且前两个参数得有一个为true,才会启动合并操作,默认16000000
Hive在对结果文件进行合并时会执行一个额外的map-only脚本,mapper的数量是文件总大小除以size.per.task参数所得的值,触发合并的条件是:
根据查询类型不同,相应的mapfiles/mapredfiles参数需要打开;
结果文件的平均大小需要大于avgsize参数的值。
hive.map.aggr=true; Map 端部分聚合,相当于Combiner
hive.groupby.mapaggr.checkinterval =100000 在 Map 端进行聚合操作的条目数目
hive.groupby.skewindata=true; 这个是给groupby优化的。会生成2个mr job,其中第一个相当于是combiner的作用,会先做一部分聚合再给reduce传过去
1.3 mapjoin 和 streamtable
这两个类似于注解一样,放在 select 的后面即可
1.3.1 mapjoin
适合于:N个较大的表,一个较小的表
mapjoin 会把指定的小表在客户端打成一个哈希表序列化文件的压缩包,通过分布式缓存均匀分发到作业执行的每一个结点上。然后在结点上进行解压,在内存中完成关联,有一个超级小表的情况下,目前hive能做到自动判断并转为map join。Map Join全过程不会使用Reduce,非常均匀,不会存在数据倾斜问题
set hive.auto.convert.join = true; # 默认为false
该参数为true时,Hive自动对左边的表统计量,如果是小表就加入内存,即对 小表使用Map join
set hive.mapjoin.smalltable.filesize;
hive.mapjoin.smalltable.filesize=25000000
大表小表的阈值默认值是25mb
1.3.2 streamtable
适合于:N个较小的表,一个超大的表
join一般都是在reduce阶段完成的,因为在map阶段无法使同样key值的分在一个map上。
而在reduce阶段的join,hive默认把左表数据(小表)放在缓存中,右表数据(大表)放入到磁盘中,然后把内存中的表的数据逐条与硬盘上user表的数据做Join。
通过/*+ streamtable(大表表名) */来指定大表。
最好每次写join时,小表放左边,大表放右边。
1.4 单纯的多对多
主键拼接一个rand(1),放入不同的reduce,group by 的时候把真正的主键做一个截取即可
2. MapReduce 中的数据倾斜
2.1 小文件倾斜
原理和Hive是一样的,太多的小文件,导致在ApplicationMaster在向ResourceManager去申请资源时,要频繁访问HDFS的NameNode,再去DataNode拿数据,准备数据时间太长。
所以可以在 map 端开始之前先把小文件进行合并,再传递给MapReduce。比如客户端产生数据文件时进行合并,或者文件数据进入map之前通过继承CombineFileInputFormat类实现小文件的合并。job.setInputFormatClass(CombineTextInputFormat.class),然后在代码里的Configuration中设置切分的块的最小值最大值等等,在同一节点上的数据块会合并,超过最大值就生产新的分片。
hadoopConf.set("mapreduce.input.fileinputformat.split.maxsize", "512000000")
hadoopConf.set("mapreduce.input.fileinputformat.split.minsize", "268435456")
2.2 key 值倾斜
同一个key的数据太多,导致全部传递到一个reduce上,导致其中一个reduce运行时间过长。
可以先创建一个类,通过 extends Partitioner 来重写 int getPartition() 方法,将key先都拼接一个rand()随机数,但是这个随机数应该和最多能启动起来的reduceNum个数是一样的(感觉是这样,随机数不能太多不一样的值,不然会传递到太多的reduce上,虽然每个reduceTask上的数据相对少了,但是启动过多的reduceTask也会增加时间),然后再创建一个类,通过 extends WritableComparator 来重写 public int compare(WritableComparable a, WritableComparable b) 方法,reduce 会自动调用 WritableComparator 类中的 int compare 方法,来判断循环的key是否和前一个是同一个来做累加,所以如果修改了partition分区方法,一般都是需要再覆写 WritableComparator 类的。
3. Spark 中的数据倾斜
数据源数据文件不均匀
SparkContext.textFile("") 读取文件数据的时候底层实现是通过Hadoop读取文件的方式
在 Hadoop 读取文件时,会通过
getPartitions()方法来获取分区,在这个方法里会调用 InputFormat 这个抽象类的getSplits()方法,这个方法的具体实现是在 FileInputFormat 类中对getSplits()方法进行覆写。如何去切分文件数据的思路是:- inputPath 如果是一个文件夹的话,遍历里面的所有文件,累加所有文件的size作为totalSize
- 求一个平均文件大小
goalSize = totalSize / numSplits; // numSplits 指的是 min(想要的分区个数,默认分区个数2个) 在spark里面是这样的,mr可能是读的配置 while(fileSize / goalSize > 1.1L){fileSize -= goalSize}如果当前文件的大小超过平均大小的1.1倍,那么就从平均大小对应的offset那里进行切分文件- 综上,如果文件不可切分,那么一个分区就是那一整个不可切分文件;如果文件可切分,计算出一个理想文件大小,然后依次判断文件大小和这个理想文件大小的关系,幅度在1.1倍之内的都可以接受,否则就需要切割。
每一个partition都会是一个task,所以如果文件不可分割,那么就会input一个特别大的文件,造成倾斜
适用场景:对于数据源单个spark input read数据量过大,或者单个task 相对于其他task spark input read较大的情况,读取数据源明显不均匀
解决方式:尽量使用可切割的文本存储,生成尽量多的task进行并行计算
优点:从数据源避免倾斜,并且从源头增大并行度,避免倾斜
缺点:需要改造数据源,支持可切割计算过程中key的分布不均(Shuffle导致的数据不均,在进行shuffle的时候,必须将各个节点上相同的key拉取到某个节点上的一个task来进行处理,此时如果某个key对应的数据量特别大的话,就会发生数据倾斜)
- 单个rdd中进行groupby的时候key分布不均
groupby(customerPart)
map(key+rand()).reducebykey().reducebykey() 执行两次 - 多个rdd进行join过程中key的不均匀
- 一个大表和一个小表的时候,将较小的RDD中的数据存到一个Broadcast变量(即广播变量)中,先广播到各个节点中,即在每个节点的内存中缓存一份,然后对大表RDD进行map算子,从Broadcast变量中获取较小RDD的全量数据,与当前RDD的每一条数据按照连接key进行比对,如果连接key相同的话,那么就将两个RDD的数据用你需要的方式连接起来。需要调整一下广播的阈值。
- 单个rdd中进行groupby的时候key分布不均
DataSkew 数据倾斜的更多相关文章
- Spark数据倾斜及解决方案
一.场景 1.绝大多数task执行得都非常快,但个别task执行极慢.比如,总共有100个task,97个task都在1s之内执行完了,但是剩余的task却要一两分钟.这种情况很常见. 2.原本能够正 ...
- [MapReduce_add_3] MapReduce 通过分区解决数据倾斜
0. 说明 数据倾斜及解决方法的介绍与代码实现 1. 介绍 [1.1 数据倾斜的含义] 大量数据发送到同一个节点进行处理,造成此节点繁忙甚至瘫痪,而其他节点资源空闲 [1.2 解决数据倾斜的方式] 重 ...
- 读取hdfs文件之后repartition 避免数据倾斜
场景一: api: textFile("hfds://....").map((key,value)).reduceByKey(...).map(实际的业务计算逻辑) 场景:hdf ...
- Hive_数据倾斜处理
Hive中三种join map join (小表join大表,将小表加入到内存) 设置map join: hive.auto.convert.join=true hive.mapjoin.smallt ...
- [大牛翻译系列]Hadoop(14)MapReduce 性能调优:减小数据倾斜的性能损失
6.4.4 减小数据倾斜的性能损失 数据倾斜是数据中的常见情况.数据中不可避免地会出现离群值(outlier),并导致数据倾斜.这些离群值会显著地拖慢MapReduce的执行.常见的数据倾斜有以下几类 ...
- hive大数据倾斜总结
在做Shuffle阶段的优化过程中,遇到了数据倾斜的问题,造成了对一些情况下优化效果不明显.主要是因为在Job完成后的所得到的 Counters是整个Job的总和,优化是基于这些Counters得出的 ...
- Spark性能优化之道——解决Spark数据倾斜(Data Skew)的N种姿势
原创文章,同步首发自作者个人博客转载请务必在文章开头处注明出处. 摘要 本文结合实例详细阐明了Spark数据倾斜的几种场景以及对应的解决方案,包括避免数据源倾斜,调整并行度,使用自定义Partitio ...
- Hive数据倾斜解决方法总结
数据倾斜是进行大数据计算时最经常遇到的问题之一.当我们在执行HiveQL或者运行MapReduce作业时候,如果遇到一直卡在map100%,reduce99%一般就是遇到了数据倾斜的问题.数据倾斜其实 ...
- Spark性能调优之解决数据倾斜
Spark性能调优之解决数据倾斜 数据倾斜七种解决方案 shuffle的过程最容易引起数据倾斜 1.使用Hive ETL预处理数据 • 方案适用场景:如果导致数据倾斜的是Hive表.如果该Hiv ...
随机推荐
- Docker:二、开始部署第一个Asp.net应用
各位看官大家好,接着上一篇,我们构建自己的镜像文件成功之后,准备开始部署自己的第一个docker应用了... 接着上文,我们构建自己的镜像,如下是Dockerfile文件 #引入运行环 ...
- 从四个问题透析Linux下C++编译&链接
摘要:编译&链接对C&C++程序员既熟悉又陌生,熟悉在于每份代码都要经历编译&链接过程,陌生在于大部分人并不会刻意关注编译&链接的原理.本文通过开发过程中碰到的四个典型 ...
- 实现element-ui对话框可拖拽功能
element-ui对话框可拖拽及边界处理 应业务需求,需要实现对话框可拖拽问题,应element-ui没有提供官方支持,于是便参考大神的文章,得出了适合业务需要的解决方案.很多大神给出的代码是没有解 ...
- 《Head First 设计模式》:代理模式
正文 一.定义 代理模式为另一个对象提供一个替身或占位符以控制对这个对象的访问. 要点: 代理模式为一个对象创建了代理对象,让代理对象控制对该对象的访问.被代理的对象可以是远程的对象.创建开销大的对象 ...
- 国产化之路-安装达梦DM8数据库
专题目录 国产化之路-统信UOS操作系统安装 国产化之路-国产操作系统安装.net core 3.1 sdk 国产化之路-安装WEB服务器 国产化之路-安装达梦DM8数据库 国产化之路-统信UOS + ...
- Layman H5+Webapp+MUI App 页面滑至到底部自动加载新的内容
要点:使用jquery的scroll()方法实现,当用户滚动指定的元素时,会发生 scroll 事件 scroll 事件适用于所有可滚动的元素和 window 对象(浏览器窗口) scroll() 方 ...
- 042 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 04 案例演示while循环的使用——循环输出英文字母
042 01 Android 零基础入门 01 Java基础语法 05 Java流程控制之循环结构 04 案例演示while循环的使用--循环输出英文字母 本文知识点:案例演示while循环的使用2 ...
- JVM内存布局(又叫Java运行时数据区)
JVM 堆中的数据是共享的,是占用内存最大的一块区域. 可以执行字节码的模块叫作执行引擎. 执行引擎在线程切换时怎么恢复?依靠的就是程序计数器. JVM 的内存划分与多线程是息息相关的.像我们程序中运 ...
- 1.入门篇十分钟了解Spring Cloud
文章目录 Spring Cloud入门系列汇总 为什么需要学习Spring Cloud 什么是Spring Cloud 设计目标与优缺点 设计目标 优缺点 Spring Cloud发展前景 整体架构 ...
- ansible-playbook模板化(jinja2)
1. ansible-playbook模板化(jinja2)条件与循环 1.1) jinja使用结构图 2. 编写jinja2的循环 2.1) 编写jinja2模板 1 [root@test-1 ...