1、什么是数据倾斜?

由于数据分布不均匀,造成数据大量的集中到一点,造成数据热点

2、Hadoop 框架的特性

  A、不怕数据大,怕数据倾斜

  B、Jobs 数比较多的作业运行效率相对比较低,如子查询比较多

  C、 sum,count,max,min 等聚集函数,通常不会有数据倾斜问题

3、主要表现

任务进度长时间维持在 99%或者 100%的附近,查看任务监控页面,发现只有少量 reduce 子任务未完成,因为其处理的数据量和其他的 reduce 差异过大。 单一 reduce 处理的记录数和平均记录数相差太大,通常达到好几倍之多,最长时间远大 于平均时长。

4、容易数据倾斜情况

  A、group by 不和聚集函数搭配使用的时候

  B、count(distinct),在数据量大的情况下,容易数据倾斜,因为 count(distinct)是按 group by 字段分组,按 distinct 字段排序

  C、 小表关联超大表 join

5、产生数据倾斜的原因

  A:key 分布不均匀

  B:业务数据本身的特性

  C:建表考虑不周全

  D:某些 HQL 语句本身就存在数据倾斜

6、业务场景

(1)空值产生的数据倾斜

场景说明

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

解决方案

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

select * from log a join user b on a.user_id is not null and a.user_id = b.user_id
union all
select * from log c where c.user_id is null;

解决方案 2:赋予空值新的 key 值

select * from log a left outer join user 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 是 1。这个优化适合无效 id(比如-99,’’,null)产 生的数据倾斜,把空值的 key 变

成一个字符串加上一个随机数,就能把造成数据倾斜的 数据分到不同的 reduce 上解决数据倾斜的问题。

改变之处:使本身为 null 的所有记录不会拥挤在同一个 reduceTask 了,会由于有替代的 随机字符串值,而分散到了多个 reduceTask 中了,由于 null 值关联不上,处理后并不影响最终结果。

(2)不同数据类型关联产生数据倾斜

场景说明

用户表中 user_id 字段为 int,log 表中 user_id 为既有 string 也有 int 的类型, 当按照两个表的 user_id 进行 join 操作的时候,默认的 hash 操作会按照 int 类型的 id 进 行分配,这样就会导致所有的 string 类型的 id 就被分到同一个 reducer 当中

解决方案

把数字类型 id 转换成 string 类型的 id

select * from user a left outer join log b on b.user_id = cast(a.user_id as string)

(3)大小表关联查询产生数据倾斜

注意:使用map join解决小表关联大表造成的数据倾斜问题。这个方法使用的频率很高。

map join 概念:将其中做连接的小表(全量数据)分发到所有 MapTask 端进行 Join,从 而避免了 reduceTask,前提要求是内存足以装下该全量数据

以大表 a 和小表 b 为例,所有的 maptask 节点都装载小表 b 的所有数据,然后大表 a 的 一个数据块数据比如说是 a1 去跟 b 全量数据做链接,就省去了 reduce 做汇总的过程。 所以相对来说,在内存允许的条件下使用 map join 比直接使用 MapReduce 效率还高些, 当然这只限于做 join 查询的时候。

在 hive 中,直接提供了能够在 HQL 语句指定该次查询使用 map join,map join 的用法是 在查询/子查询的SELECT关键字后面添加/*+ MAPJOIN(tablelist) */提示优化器转化为map join(早期的 Hive 版本的优化器是不能自动优化 map join 的)。其中 tablelist 可以是一个 表,或以逗号连接的表的列表。tablelist 中的表将会读入内存,通常应该是将小表写在 这里。

MapJoin 具体用法:

select /* +mapjoin(a) */ a.id aid, name, age from a join b on a.id = b.id;
select /* +mapjoin(movies) */ a.title, b.rating from movies a join ratings b on a.movieid =
b.movieid;

在 hive0.11 版本以后会自动开启 map join 优化,由两个参数控制:

set hive.auto.convert.join=true; //设置 MapJoin 优化自动开启

set hive.mapjoin.smalltable.filesize=25000000 //设置小表不超过多大时开启 mapjoin 优化

如果是大大表关联呢?那就大事化小,小事化了。把大表切分成小表,然后分别 map join

那么如果小表不大不小,那该如何处理呢???

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

举一例:日志表和用户表做链接

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

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

改进方案:

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 = x.user_id;

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

Hive学习之路 (十九)Hive的数据倾斜相关推荐

  1. Hive学习之路 (九)Hive的内置函数

    数学函数 Return Type Name (Signature) Description DOUBLE round(DOUBLE a) Returns the rounded BIGINT valu ...

  2. Hive学习之路(二):Hive表操作详讲

    操作内容简介 一.操作前的准备 二.Hive表操作详讲 1. 创建数据库 2. 查看所有数据库/表 3. 在Hive上直接操作HDFS 4. 在Hive上直接执行终端命令 5. 创建数据表/查看表的信 ...

  3. DLL基础——Windows核心编程学习手札之十九

    DLL基础 --Windows核心编程学习手札之十九 Windows API中的所有函数都包含在DLL中,3个最重要的DLL是Kernel32.dll,它包含用于管理内存.进程和线程的各个函数:Use ...

  4. javaweb学习总结(三十九)——数据库连接池

    javaweb学习总结(三十九)--数据库连接池 一.应用程序直接获取数据库连接的缺点 用户每次请求都需要向数据库获得链接,而数据库创建连接通常需要消耗相对较大的资源,创建时间也较长.假设网站一天10 ...

  5. C/C++学习之路_九:文件操作

    C/C++学习之路_九:文件操作 目录 概述 文件的顺序读写 文件的随机读写 windows和linux文本 获取文件状态 删除文件.重命名文件 文件缓冲区 1. 概述 1. 磁盘文件和设备文件 磁盘 ...

  6. python数据挖掘学习笔记】十九.鸢尾花数据集可视化、线性回归、决策树花样分析

    #2018-04-05 16:57:26 April Thursday the 14 week, the 095 day SZ SSMR python数据挖掘学习笔记]十九.鸢尾花数据集可视化.线性回 ...

  7. JavaScript学习(八十九)—数组练习题

    JavaScript学习(八十九)-数组练习题

  8. JavaScript学习(七十九)—值传递和地址传递

    JavaScript学习(七十九)-值传递和地址传递 一.值传递 二.地址传递

  9. JavaScript学习(六十九)—正则表达式实训题

    JavaScript学习(六十九)-正则表达式实训题 复习一下所学的知识 实训练习

  10. JavaScript学习(五十九)—原型、原型链、闭包以及闭包的不足

    JavaScript学习(五十九)-原型.原型链.闭包以及闭包的不足 一.什么是闭包? 所谓闭包就是指被定义在其他函数内部的函数. 闭包函数可以访问它所在的函数的所有变量. 文字太抽象了,画图解释一下 ...

最新文章

  1. I.MX6 Android 5.1 纯Linux、U-Boot编译
  2. springboot事物注解不生效_SpringBoot攻略三、配置文件说明
  3. javascript的程序控制结构及语句------(2)循环控制语句、跳转语句、对话框
  4. docker容器的标准使用过程_phpStorm中使用xdebug工具调试docker容器中的程序
  5. 160 - 33 Cruehead.1
  6. LCP 07. 传递信息
  7. pytorch之创建数据集
  8. How To Use Google Logging Library (glog)
  9. 西瓜书读书笔记5-决策树的分裂原则
  10. StanfordDB class自学笔记 (13) Views and Authorization
  11. 我在2016年读到的
  12. 禁忌搜索算法(Tabu Search)
  13. Linux bpf 1.1、BPF内核实现
  14. VMware虚拟机软件账号的注册问题
  15. javascript 实现table展开折叠
  16. 新浪短连接(t.cn)在线生成工具
  17. 补交20145226蓝墨云班课 -- MyOD
  18. 读书笔记 - 《卧底经济学》
  19. 笨办法学python3 学习笔记 习题20-21
  20. EBAZ4205矿板使用PS端时钟,给PL端,LED流水灯功能

热门文章

  1. Java字符串连接的几种方式
  2. ecshop商品列表页增加/显示货号SN
  3. Java 类锁、对象锁、私有锁
  4. 黄海造船周身流动的信息化血液
  5. ES6的介绍和let的使用|-ES6连载1
  6. 脚本——web_custom_request函数详解
  7. git push本地代码到github出错
  8. 如何快速清理Mac系统上的大额文件
  9. LeetCode(160): Intersection of Two Linked Lists
  10. linux Socket send与recv函数详解