数据倾斜是指,map /reduce程序执行时,reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理时间很长,这是因为某一个key的条数比其他key多很多(有时是百倍或者千倍之多),这条key所在的reduce节点所处理的数据量比其他节点就大很多,从而导致某几个节点迟迟运行不完。

阿里的这篇比较实用,通俗易懂:数据倾斜总结 http://www.tbdata.org/archives/2109

有篇分析比较详细,如果需要使用可以细读:http://blog.csdn.net/core_cto/article/details/8644692 浅析
Hadoop 中的数据倾斜

·         症状和原因:

·    操作:join,group by,count distinct

·    原因:key分布不均匀,人为的建表疏忽,业务数据特点。

·    症状:任务进度长时间维持在99%(或100%),查看任务监控页面,发现只有少量(1个或几个)reduce子任务未完成;查看未完成的子任务,可以看到本地读写数据量积累非常大,通常超过10GB可以认定为发生数据倾斜。

·    倾斜度:平均记录数超过50w且最大记录数是超过平均记录数的4倍;最长时长比平均时长超过4分钟,且最大时长超过平均时长的2倍。

我遇到的问题:

select * from a join b;

1. a表1000多万,b表不到2亿,用mapjoin显然不行;

2.
设置参数 set hive.groupby.skewindata=true,不起作用;

3.
由于关连键为手机号,自认为业务数据上不存在数据倾斜;

后来通过查看每个表里面关联键的分布,才发现两个表里面都存在空串'',而且严重倾斜,大表里面的空串数量有400多万。

将两个表的空串过滤后再进行关联,job时间由原来的40多分钟减少到2分钟。

总结:

1. 数据倾斜的原因就那么几种,逐一排查;

2. 细心,动手,不能光凭感觉来判定;

3. 判定某一个表的key是否存在数据倾斜,就是group by key,取top N来看;

附:数据倾斜常用解决方法:

1. 万能膏药:hive.groupby.skewindata=true

2. 大小表关联:将key相对分散,并且数据量小的表放在join的左边,这样有效减少内存溢出错误发生几率;再进一步,可用map join让小的维度表(1000条以下的记录条数)先进内存。在map端完成reduce.

3. 大表和大表关联:把空值的key变成一个字符串加上随机数,把倾斜的数据分到不同的reduce上,由于null值关联不上,处理后并不影响最终结果。

4. count distinct大量相同特殊值:(空值单独处理)count distinct时,将值为空的情况单独处理,如果是计算count distinct,可以不用处理,直接过滤,在最后结果中加1。如果还有其他计算,需要进行group
by,可以先将值为空的记录单独处理,再和其他计算结果进行union。

用hadoop程序进行数据关联时,常碰到数据倾斜的情况,这里提供一种解决方法。

(1)设置一个hash份数N,用来对条数众多的key进行打散。

(2)对有多条重复key的那份数据进行处理:从1到N将数字加在key后面作为新key,如果需要和另一份数据关联的话,则要重写比较类和分发类(方法如上篇《hadoop
job解决大数据量关联的一种方法》)。如此实现多条key的平均分发。

int iNum = iNum % iHashNum;

String strKey = key + CTRLC + String.valueOf(iNum) + CTRLB + “B”;

(3)上一步之后,key被平均分散到很多不同的reduce节点。如果需要和其他数据关联,为了保证每个reduce节点上都有关联的key,对另一份单一key的数据进行处理:循环的从1到N将数字加在key后面作为新key

for(int i = 0; i < iHashNum; ++i){

String strKey =key + CTRLC + String.valueOf(i) ;

output.collect(new Text(strKey), new Text(strValues));}

以此解决数据倾斜的问题,经试验大大减少了程序的运行时间。但此方法会成倍的增加其中一份数据的数据量,以增加shuffle数据量为代价,所以使用此方法时,要多次试验,取一个最佳的hash份数值。

======================================

用上述的方法虽然可以解决数据倾斜,但是当关联的数据量巨大时,如果成倍的增长某份数据,会导致reduce shuffle的数据量变的巨大,得不偿失,从而无法解决运行时间慢的问题。

有一个新的办法可以解决成倍增长数据的缺陷:

在两份数据中找共同点。用重复较少的某个属性作为分布给reduce的依据。比如两份数据里除了关联的字段以外,还有另外相同含义的字段,如果这个字段在所有log中的重复率比较小,则用这个字段计算hash值,如果是数字,直接用来模hash的份数,如果是字符可以用hashcode来模hash的份数(当然数字为了避免落到同一个reduce上的数据过多,也可以用hashcode),这样如果字段值分布足够平均就可以解决上述问题。

我到过的处理的方式

1.mapjoin方式

/*+ MAPJOIN(c,d,e,f) */

其中c,d,e,f是你小表,也就是说可能会倾斜数据的表;

但是对于join,在判断小表不大于1G的情况下,使用map join,也就是要考虑c,d,e,f等表的大小,不能超过内存限制,否则会出现OOM错误;



2.控制空值分布

  1. select
  2. '${date}' as thedate,
  3. a.search_type,
  4. a.query,
  5. a.category,
  6. a.cat_name,
  7. a.brand_id,
  8. a.brand_name,
  9. a.dir_type,
  10. a.rewcatid,
  11. a.new_cat_name,
  12. a.new_brand_id,
  13. f.brand_name as new_brand_name,
  14. a.pv,
  15. a.uv,
  16. a.ipv,
  17. a.ipvuv,
  18. a.trans_amt,
  19. a.trans_num,
  20. a.alipay_uv
  21. from fdi_search_query_cat_qp_temp a
  22. left outer join brand f
  23. on
  24. f.pt='${date}000000'
  25. and case when a.new_brand_id is
    null then concat('hive',rand() )
    else a.new_brand_id end = f.brand_id;
select
'${date}' as thedate,
a.search_type,
a.query,
a.category,
a.cat_name,
a.brand_id,
a.brand_name,
a.dir_type,
a.rewcatid,
a.new_cat_name,
a.new_brand_id,
f.brand_name as new_brand_name,
a.pv,
a.uv,
a.ipv,
a.ipvuv,
a.trans_amt,
a.trans_num,
a.alipay_uv
from fdi_search_query_cat_qp_temp a
left outer join brand f
on
f.pt='${date}000000'
and case when a.new_brand_id is null then concat('hive',rand() ) else a.new_brand_id end = f.brand_id;

这样的写法把空值的 key 变成一个字符串加上随机数,就能把倾斜的数据分到不同的reduce上 ,解决数据倾斜问题。



如果上述的方法还不能解决,比如当有多个JOIN的时候,建议建立临时表,然后拆分HIVE SQL语句;

关于数据倾斜,阿里集团数据平台上的博客文章有很好的几个方法,敢兴趣的人也可以去看一下:http://www.tbdata.org/archives/2109



3.关于nonstrict

join同样一张表多次的时候,会出现这样的错误信息:

FAILED: Error in semantic analysis: In strict mode, cartesian product is not allowed. If you really want to perform the operation, set hive.mapred.mode=nonstrict

解决方式是在SQL前面加上如下:

set hive.mapred.mode=nonstrict;

strict模式在下面三种情况下有限制:

(1) partition表需要加上分区裁剪

(2) order by 只有一个reduce,需要加上limit

(3) join时,如果只有一个reduce,笛卡尔积不支持。



HIVE小技巧:

1.hive sql中:

sum(t.shop_gmvcount + t.GMVCOUNT_NEW + t.auc_shop_gmvcount + t.spu_gmv_cnt) gmv_cnt,

这样的统计结果,当t.t.shop_gmvcount为NULL时,即使后面的t.GMVCOUNT_NEW 不为null,那么总计的结果这个计算仍然是NULL;

修改的方法是:采用sum(coalesce(t.shop_gmvcount,cast(0 as bigint)) + coalesce(t.GMVCOUNT_NEW,cast(0 as bigint))

这样的方式,coalesce函数类似于ORACLE数据库里面的nvl



2。join中where的过滤,on里面才能起到表的过滤,放在where里面起不到提前过滤的情况;



3.left semi jioin的使用

LEFT SEMI JOIN 是 IN/EXISTS 子查询的一种更高效的实现。Hive 当前没有实现 IN/EXISTS 子查询,所以你可以用 LEFT SEMI JOIN 重写你的子查询语句。LEFT SEMI JOIN 的限制是, JOIN 子句中右边的表只能在 ON 子句中设置过滤条件,在 WHERE 子句、SELECT 子句或其他地方过滤都不行。

hadoop 数据倾斜的更多相关文章

  1. 深入理解hadoop数据倾斜

    深入理解hadoop之数据倾斜 1.什么是数据倾斜 我们在用map /reduce程序执行时,有时候会发现reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理 ...

  2. Hadoop数据倾斜及解决办法

    数据倾斜:就是大量的相同key被partition分配到一个分区里,map /reduce程序执行时,reduce节点大部分执行完毕,但是有一个或者几个reduce节点运行很慢,导致整个程序的处理时间 ...

  3. [大牛翻译系列]Hadoop(14)MapReduce 性能调优:减小数据倾斜的性能损失

    6.4.4 减小数据倾斜的性能损失 数据倾斜是数据中的常见情况.数据中不可避免地会出现离群值(outlier),并导致数据倾斜.这些离群值会显著地拖慢MapReduce的执行.常见的数据倾斜有以下几类 ...

  4. Hadoop基础-MapReduce的数据倾斜解决方案

    Hadoop基础-MapReduce的数据倾斜解决方案 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.数据倾斜简介 1>.什么是数据倾斜 答:大量数据涌入到某一节点,导致 ...

  5. hadoop job解决大数据量关联时数据倾斜的一种办法

    转自:http://www.cnblogs.com/xuxm2007/archive/2011/09/01/2161929.html http://www.geminikwok.com/2011/04 ...

  6. 浅析 Hadoop 中的数据倾斜

    转自:http://my.oschina.net/leejun2005/blog/100922 最近几次被问到关于数据倾斜的问题,这里找了些资料也结合一些自己的理解. 在并行计算中我们总希望分配的每一 ...

  7. hadoop之数据倾斜

    数据倾斜介绍 在做Shuffle阶段的优化过程中,遇到了数据倾斜的问题,造成了对一些情况下优化效果不明显.主要是因为在Job完成后的所得到的Counters是整个Job的总和,优化是基于这些Count ...

  8. Spark性能优化之道——解决Spark数据倾斜(Data Skew)的N种姿势

    原创文章,同步首发自作者个人博客转载请务必在文章开头处注明出处. 摘要 本文结合实例详细阐明了Spark数据倾斜的几种场景以及对应的解决方案,包括避免数据源倾斜,调整并行度,使用自定义Partitio ...

  9. Hive的HQL语句及数据倾斜解决方案

    [版权申明:本文系作者原创,转载请注明出处] 文章出处:http://blog.csdn.net/sdksdk0/article/details/51675005 作者: 朱培          ID ...

随机推荐

  1. Scikit-learn:主要模块和基本使用方法

    http://blog.csdn.net/pipisorry/article/details/52128222 scikit-learn: Machine Learning in Python.sci ...

  2. Android Multimedia框架总结(十三)CodeC部分之OpenMAX框架初识及接口与适配层实现

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52629598 前言:上篇中介绍O ...

  3. 21 FragmentTabHost +Fragment代码案例

    注意头导航标签过多会被压缩并 结构 MainActivity.java package com.qf.day21_fragmenttabhost_demo1; import com.qf.day21_ ...

  4. Swift的print不换行打印的方法

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) swift大多数情况下我们直接用默认的print函数打印就可以 ...

  5. 程序员必须搞清的概念-equals和=和hashcode的区别

    1. 首先equals()和hashcode的介绍 equals 方法在非空对象引用上实现相等关系: * 自反性:对于任何非空引用值 x,x.equals(x) 都应返回 true. * 对称性:对于 ...

  6. Socket实现聊天客户端

    今天在极客学院上看到了一个关于Socket的视频讲解,感觉还不错,就写了份代码,拿来分享一下. Socket使用方法 关于Socket的使用,我们首先要弄清楚的是,在服务器端还是在客户端使用.因为这的 ...

  7. UNIX网络编程——套接字选项(SOL_SOCKET级别)

    #include <sys/socket.h> int setsockopt( int socket, int level, int option_name,const void *opt ...

  8. python类:描述器Descriptors和元类MetaClasses

    http://blog.csdn.net/pipisorry/article/details/50444769 描述器(Descriptors) 描述器决定了对象属性是如何被访问的.描述器的作用是定制 ...

  9. Java-IO之ByteArrayOutputStream

    ByteArrayOutputSTream是字节数组输出流,继承于OutputStream.ByteArrayOutputStream中的数据被写入到一个byte数组中,缓冲区会随着数据的不断写入而自 ...

  10. JSP标签JSTL(5)--常用的标签函数

    在使用JSTL的标签函数的时候请务必加上如下代码 <!-- 添加jsp标签的核心库 --> <%@ taglib uri="http://java.sun.com/jsp/ ...