select怎么设置默认值_20200817:详细说下数据倾斜怎么解决?

福哥答案2020-08-17:

数据倾斜是大数据领域绕不开的拦路虎,当你所需处理的数据量到达了上亿甚至是千亿条的时候,数据倾斜将是横在你面前一道巨大的坎。很可能有几周甚至几月都要头疼于数据倾斜导致的各类诡异的问题。

数据倾斜是指:mapreduce程序执行时,reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理时间很长,这是因为某一个key的条数比其他key多很多(有时是百倍或者千倍之多),这条key所在的reduce节点所处理的数据量比其他节点就大很多,从而导致某几个节点迟迟运行不完。Hive的执行是分阶段的,map处理数据量的差异取决于上一个stage的reduce输出,所以如何将数据均匀的分配到各个reduce中,就是解决数据倾斜的根本所在。

以下是一些常见的数据倾斜情形:

bcfed97a2499e983f3fbdda04d5930ab.png

一、Group by 倾斜

group by造成的倾斜相对来说比较容易解决。hive提供两个参数可以解决:

1.1 hive.map.aggr

一个是hive.map.aggr,默认值已经为true,他的意思是做map aggregation,也就是在mapper里面做聚合。这个方法不同于直接写mapreduce的时候可以实现的combiner,但是却实现了类似combiner的效果。事实上各种基于mr的框架如pig,cascading等等用的都是map aggregation(或者叫partial aggregation)而非combiner的策略,也就是在mapper里面直接做聚合操作而不是输出到buffer给combiner做聚合。对于map aggregation,hive还会做检查,如果aggregation的效果不好,那么hive会自动放弃map aggregation。判断效果的依据就是经过一小批数据的处理之后,检查聚合后的数据量是否减小到一定的比例,默认是0.5,由hive.map.aggr.hash.min.reduction这个参数控制。所以如果确认数据里面确实有个别取值倾斜,但是大部分值是比较稀疏的,这个时候可以把比例强制设为1,避免极端情况下map aggr失效。hive.map.aggr还有一些相关参数,比如map aggr的内存占用等,具体可以参考这篇文章。

1.2 hive.groupby.skewindata

另一个参数是hive.groupby.skewindata。这个参数的意思是做reduce操作的时候,拿到的key并不是所有相同值给同一个reduce,而是随机分发,然后reduce做聚合,做完之后再做一轮MR,拿前面聚合过的数据再算结果。所以这个参数其实跟hive.map.aggr做的是类似的事情,只是拿到reduce端来做,而且要额外启动一轮job,所以其实不怎么推荐用,效果不明显。

1.3 count distinct 改写

另外需要注意的是count distinct操作往往需要改写SQL,可以按照下面这么做:

```bash

/*改写前*/

select a, count(distinct b) as c from tbl group by a;

/*改写后*/

select a, count(*) as c from (select a, b from tbl group by a, b) group by a;

```

二、Join倾斜

2.1 skew join

join造成的倾斜,常见情况是不能做map join的两个表(能做map join的话基本上可以避免倾斜),其中一个是行为表,另一个应该是属性表。比如我们有三个表,一个用户属性表users,一个商品属性表items,还有一个用户对商品的操作行为表日志表logs。假设现在需要将行为表关联用户表:

```bash

select * from logs a join users b on a.user_id = b.user_id;

```

其中logs表里面会有一个特殊用户user_id = 0,代表未登录用户,假如这种用户占了相当的比例,那么个别reduce会收到比其他reduce多得多的数据,因为它要接收所有user_id = 0的记录进行处理,使得其处理效果会非常差,其他reduce都跑完很久了它还在运行。

hive给出的解决方案叫skew join,其原理把这种user_id = 0的特殊值先不在reduce端计算掉,而是先写入hdfs,然后启动一轮map join专门做这个特殊值的计算,期望能提高计算这部分值的处理速度。当然你要告诉hive这个join是个skew join,即:set

> hive.optimize.skewjoin = true;

还有要告诉hive如何判断特殊值,根据hive.skewjoin.key设置的数量hive可以知道,比如默认值是100000,那么超过100000条记录的值就是特殊值。总结起来,skew join的流程可以用下图描述:

bea02fe39ae31a1f1eb98fc1f0082808.png

2.2 特殊值分开处理法

不过,上述方法还要去考虑阈值之类的情况,其实也不够通用。所以针对join倾斜的问题,一般都是通过改写sql解决。对于上面这个问题,我们已经知道user_id = 0是一个特殊key,那么可以把特殊值隔离开来单独做join,这样特殊值肯定会转化成map join,非特殊值就是没有倾斜的普通join了:

```bash

select

*

from

(

select * from logs where user_id = 0

)

a

join

(

select * from users where user_id = 0

)

b

on

a.user_id = b.user_id

union all

select * from logs a join users b on a.user_id <> 0 and a.user_id = b.user_id;

```

2.3 随机数分配法

上面这种个别key倾斜的情况只是一种倾斜情况。最常见的倾斜是因为数据分布本身就具有长尾性质,比如我们将日志表和商品表关联:

```bash

select * from logs a join items b on a.item_id = b.item_id;

```

这个时候,分配到热门商品的reducer就会很慢,因为热门商品的行为日志肯定是最多的,而且我们也很难像上面处理特殊user那样去处理item。这个时候就会用到加随机数的方法,也就是在join的时候增加一个随机数,随机数的取值范围n相当于将item给分散到n个reducer:

```bash

select

a.*,

b.*

from

(

select *, cast(rand() * 10 as int) as r_id from logs

)

a

join

(

select *, r_id from items lateral view explode(range_list(1, 10)) rl as r_id

)

b

on

a.item_id = b.item_id

and a.r_id = b.r_id

```

上面的写法里,对行为表的每条记录生成一个1-10的随机整数,对于item属性表,每个item生成10条记录,随机key分别也是1-10,这样就能保证行为表关联上属性表。其中range_list(1,10)代表用udf实现的一个返回1-10整数序列的方法。这个做法是一个解决join倾斜比较根本性的通用思路,就是如何用随机数将key进行分散。当然,可以根据具体的业务场景做实现上的简化或变化。

2.4 业务设计

除了上面两类情况,还有一类情况是因为业务设计导致的问题,也就是说即使行为日志里面join key的数据分布本身并不明显倾斜,但是业务设计导致其倾斜。比如对于商品item_id的编码,除了本身的id序列,还人为的把item的类型也作为编码放在最后两位,这样如果类型1(电子产品)的编码是00,类型2(家居产品)的编码是01,并且类型1是主要商品类,将会造成以00为结尾的商品整体倾斜。这时,如果reduce的数量恰好是100的整数倍,会造成partitioner把00结尾的item_id都hash到同一个reducer,引爆问题。这种特殊情况可以简单的设置合适的reduce值来解决,但是这种坑对于不了解业务的情况下就会比较隐蔽。

三、典型的业务场景

3.1 空值产生的数据倾斜

场景:如日志中,常会有信息丢失的问题,比如日志中的 user_id,如果取其中的 user_id 和 用户表中的user_id 关联,会碰到数据倾斜的问题。

解决方法1:user_id为空的不参与关联

```bash

select

*

from

log a

join users b

on

a.user_id is not null

and a.user_id = b.user_id

union all

select * from log a where a.user_id is null;

```

解决方法2 :赋与空值分新的key值

```bash

select

*

from

log a

left outer join users b

on

case

when a.user_id is null

then concat(‘hive’, rand())

else a.user_id

end = b.user_id;

```

结论:方法2比方法1效率更好,不但io少了,而且作业数也少了。解决方法1中 log读取两次,jobs是2。解决方法2 job数是1 。这个优化适合无效 id (比如 -99 , ’’, null 等) 产生的倾斜问题。把空值的 key 变成一个字符串加上随机数,就能把倾斜的数据分到不同的reduce上 ,解决数据倾斜问题。

3.2 不同数据类型关联产生数据倾斜

场景:用户表中user_id字段为int,log表中user_id字段既有string类型也有int类型。当按照user_id进行两个表的Join操作时,默认的Hash操作会按int型的id来进行分配,这样会导致所有string类型id的记录都分配到一个Reducer中。

解决方法:把数字类型转换成字符串类型

```bash

select

*

from

users a

left outer join logs b

on

a.usr_id = cast(b.user_id as string)

```

3.3 小表不小不大,怎么用 map join 解决倾斜问题

使用 map join 解决小表(记录数少)关联大表的数据倾斜问题,这个方法使用的频率非常高,但如果小表很大,大到map join会出现bug或异常,这时就需要特别的处理。以下例子:

```bash

select * from log a left outer join users b on a.user_id = b.user_id;

```

users 表有 600w+ 的记录,把 users 分发到所有的 map 上也是个不小的开销,而且 map join 不支持这么大的小表。如果用普通的 join,又会碰到数据倾斜的问题。

```bash

select

/*+mapjoin(x)*/

*

from

log a

left outer join

(

select

/*+mapjoin(c)*/

d.*

from

(

select distinct user_id from log

)

c

join users d

on

c.user_id = d.user_id

)

x on a.user_id = b.user_id;

```

假如,log里user_id有上百万个,这就又回到原来map join问题。所幸,每日的会员uv不会太多,有交易的会员不会太多,有点击的会员不会太多,有佣金的会员不会太多等等。所以这个方法能解决很多场景下的数据倾斜问题。

四、总结

使map的输出数据更均匀的分布到reduce中去,是我们的最终目标。由于Hash算法的局限性,按key Hash会或多或少的造成数据倾斜。大量经验表明数据倾斜的原因是人为的建表疏忽或业务逻辑可以规避的。在此给出较为通用的步骤:

1)采样log表,哪些user_id比较倾斜,得到一个结果表tmp1。由于对计算框架来说,所有的数据过来,他都是不知道数据分布情况的,所以采样是并不可少的。

2)数据的分布符合社会学统计规则,贫富不均。倾斜的key不会太多,就像一个社会的富人不多,奇特的人不多一样。所以tmp1记录数会很少。把tmp1和users做map join生成tmp2,把tmp2读到distribute file cache。这是一个map过程。

3)map读入users和log,假如记录来自log,则检查user_id是否在tmp2里,如果是,输出到本地文件a,否则生成的key,value对,假如记录来自member,生成的key,value对,进入reduce阶段。

4)最终把a文件,把Stage3 reduce阶段输出的文件合并起写到hdfs。

如果确认业务需要这样倾斜的逻辑,考虑以下的优化方案:

1)对于join,在判断小表不大于1G的情况下,使用map join

2)对于group by或distinct,设定 hive.groupby.skewindata=true

3)尽量使用上述的SQL语句调节进行优化

五、参考文献

[数据分析系列(3):数据倾斜](https://blog.csdn.net/anshuai_aw1/article/details/84033160)

***

[评论](https://user.qzone.qq.com/3182319461/blog/1597618770)

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

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

相关文章

数据库查询某一列大写转化小写字母表示_基于MySQL数据库下亿级数据的分库分表...

移动互联网时代&#xff0c;海量的用户数据每天都在产生&#xff0c;基于用户使用数据的用户行为分析等这样的分析&#xff0c;都需要依靠数据都统计和分析&#xff0c;当数据量小时&#xff0c;数据库方面的优化显得不太重要&#xff0c;一旦数据量越来越大&#xff0c;系统响…

vs 启动调用的目标发生异常_协程中的取消和异常 | 取消操作详解

在日常的开发中&#xff0c;我们都知道应该避免不必要的任务处理来节省设备的内存空间和电量的使用——这一原则在协程中同样适用。您需要控制好协程的生命周期&#xff0c;在不需要使用的时候将它取消&#xff0c;这也是结构化并发所倡导的&#xff0c;继续阅读本文来了解有关…

pytorch 图像分割的交并比_Segmentation101系列-最简单的卷积网络语义分割(1)-PASCAL VOC图像分割...

作者&#xff1a;陈洪瀚 /洪瀚笔记知乎专栏摘要&#xff1a;介绍了使用PyTorch和torchvision加载训练好的全卷积网络FCN或DeepLab模型&#xff0c;并对PASCAL VOC图像进行分割并显示结果。网址&#xff1a;github代码链接, 码云代码链接陈洪瀚​www.zhihu.com一. 准备实验数据下…

系统目录结构 ls命令 文件类型 alias命令

2019独角兽企业重金招聘Python工程师标准>>> 2.1/2.2 系统目录结构 /bin&#xff1a;bin是Binary的缩写&#xff0c;该目录下存放的是最常用的命令。 /boot&#xff1a;该目录下存放的是启动Linux时使用的一些核心文件&#xff0c;包括一些连接文件以及镜像文件。 …

运维老鸟教你安装centos6.5如何选择安装包

原文&#xff1a;http://oldboy.blog.51cto.com/2561410/1564620 ------------------------------------------------------------------------------ 近来发现越来越多的运维小伙伴们都有最小化安装系统的洁癖,因此&#xff0c;找老男孩来咨询&#xff0c;这个“洁癖”好习惯…

服务器centos怎么部署_我什么都不会,怎么拥有自己的个人博客呢

博客每个人都想拥有一个属于自己的博客&#xff0c;可以分享自己的心得、技术等&#xff0c;可以很好地展示自己的作品&#xff0c;但是自己又什么都不会怎么才能拥有自己的个人博客呢&#xff1f;一、搭建个人博客需要什么呢(1)购买服务器&#xff0c;个人博客可以购买香港服务…

修改yum的镜像服务器为阿里云

1、进入阿里云镜像网站 http://mirrors.aliyun.com/ 2、选择centos---help 3、安装help里的步骤进行操作 1、备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2、下载新的CentOS-Base.repo 到/etc/yum.repos.d/ CentOS 5 wget -O /e…

java instanceof 继承_Java中的instanceof关键字

Java中&#xff0c;instanceof运算符的前一个操作符是一个引用变量&#xff0c;后一个操作数通常是一个类(可以是接口)&#xff0c;用于判断前面的对象是否是后面的类&#xff0c;或者其子类、实现类的实例。如果是返回true&#xff0c;否则返回false。也就是说&#xff1a;使用…

学习笔记-JMeter 进行接口压力测试

一、压力测试场景设置 1、场景设定&#xff1a;进行接口压力测试时&#xff0c;有单场景也有混合场景。单场景就是对一个接口进行请求&#xff1b;混合场景需要对多个接口进行请求&#xff0c;在流程类业务场景会运用到 2、压测时间设定&#xff1a;通常时间为10&#xff0d;15…

四宫格效果 css_【深度教研】智力游戏“九宫格” 集体教研活动纪实

【关键词】教研要建立过程模式&#xff0c;规范管理&#xff0c;分层推进&#xff0c;各负其责&#xff0c;及时反馈&#xff0c;展示总结。让教研的过程成为全体教师共同成长的过程。游戏和材料不是一次性的制作和一次性的使用&#xff0c;其价值在于反复玩&#xff0c;玩中学…

sql server numeric 可存几位小数_CBA中的10大传奇队长,将篮球精神一直传递下去,你认识几位呢?...

阅读本文前&#xff0c;请您先点击上面的蓝色字体“十点听情感”&#xff0c;再点击“关注”&#xff0c;这样您就可以继续免费收到最新文章了。每天都有分享。完全是免费订阅&#xff0c;请放心关注&#xff01;&#xff01;&#xff01;中国男子篮球职业联赛简称CBA中国篮球自…

设置ntpdate服务开机启动校验时间

一般linux都预装了 ntpdate 服务。 如果没有安装&#xff0c;参考博文&#xff1a;http://blog.csdn.net/zengmingen/article/details/52913486启动设置 1、检查系统服务里有没有ntpdate 使用命令&#xff1a;chkconfig --list2、设置开机启动 chkconfig 的命令详见&#xff1a…

电脑卡顿不流畅是什么原因_什么造成游戏直播画画卡顿、延迟?这三个原因了解一下...

原标题&#xff1a;什么造成游戏直播画画卡顿、延迟&#xff1f;这三个原因了解一下从事直播的朋友们相信都有所体会&#xff0c;直播时很容易出现画面卡顿、延迟的现象&#xff0c;这究竟是什么原因造成的呢&#xff1f;最可能是这几点&#xff01;1、服务器过载崩溃说起服务器…

java linux 调用32位so_从linux源码看socket(tcp)的timeout

从linux源码看socket(tcp)的timeout前言网络编程中超时时间是一个重要但又容易被忽略的问题,对其的设置需要仔细斟酌。在经历了数次物理机宕机之后,笔者详细的考察了在网络编程(tcp)中的各种超时设置&#xff0c;于是就有了本篇博文。本文大部分讨论的是socket设置为block的情况…

spark DAGScheduler、TaskSchedule、Executor执行task源码分析

摘要 spark的调度一直是我想搞清楚的东西&#xff0c;以及有向无环图的生成过程、task的调度、rdd的延迟执行是怎么发生的和如何完成的&#xff0c;还要就是RDD的compute都是在executor的哪个阶段调用和执行我们定义的函数的。这些都非常的基础和困难。花一段时间终于弄白了其中…

代码实现tan graph model for classification_自定义 Estimator 实现(以BERT为例)

本文将主要介绍tensorflow 的Estimator 这个高级API&#xff0c;它的主要作用就是提出一个高级范式&#xff08;paradigm&#xff09;&#xff0c;将模型的训练&#xff0c;验证&#xff0c;预测&#xff0c;以及保存规范起来&#xff0c;免去了tensorflow的Session.run 的操作…

英雄联盟怎么解除小窗口_英雄联盟手游怎么加好友_英雄联盟手游怎么加好友一起玩_资讯...

英雄联盟手游是腾讯联合英雄联盟开发商拳头开发的英雄联盟手游。不仅能够高度还原端游的经典操作和竞技体验&#xff0c;也具有非常多创新的元素&#xff0c;对于英雄联盟的全球生态布局具有重要意义。英雄联盟手游游戏中有非常多的英雄可以供玩家选择&#xff0c;并且拥有排位…

Sonar与jenkins集成

2019独角兽企业重金招聘Python工程师标准>>> 参考文档&#xff1a;http://blog.csdn.net/kefengwang/article/details/54377055 一.下载&#xff1a;wget https://fossies.org/linux/misc/sonarqube-7.0.zip 二.配置sonar.properties ## sudo vim /opt/sonarqube-6.…

eplan连接定义点不显示_EPLAN电气图实例--控制柜(控制面板)

EPLAN电气图实例--控制柜(控制面板)上期回顾(上期主要画了硬件的布局图)&#xff1a;这期主要画一个控制面板控制柜布局1.0 上期主要做了一个长方形的结构板&#xff0c;里面插入了一个结构盒&#xff0c;然后放置一个HMI的宏(这里是KTP1000&#xff0c;在官网随便找下就行了)&…

markdown 语法_markdown特殊语法之上下标

markdown特殊语法之上下标​markdown的基本语法很简单&#xff0c;百度一下就可以了&#xff0c;有空的话我再转载一些过来。我想的是平常其实需要用到的一些输入技巧&#xff0c;特殊用法或者扩展语法&#xff0c;还有一些难点倒是要记录学习一下。在写作的时候&#xff0c;大…