Hive学习之路 (十九)Hive的数据倾斜

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 不会太多,有交易的会员不会太多,有点击的会员不会太多,有佣金的会员不会太多等 等。所以这个方法能解决很多场景下的数据倾斜问题

原文地址:https://www.cnblogs.com/qingyunzong/p/8847597.html

时间: 2024-07-29 05:27:55

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

Linux嵌入式驱动学习之路(十九)触摸屏驱动

触摸屏使用流程: 1. 按下产生中断. 2.在中断处理程序中启动AD转换XY坐标. 3.AD转换结束并产生AD中断. 4. 在AD的中断处理函数中上报信息,启动定时器. 5. 定时器时间到后进入中断,处理长按滑动.跳转到第二步 6. 松开. sd

Android学习笔记二十九之SwipeRefreshLayout、RecyclerView和CardView

Android学习笔记二十九之SwipeRefreshLayout.RecyclerView和CardView 前面我们介绍了AlertDialog和几个常用的Dialog,ProgressDialog进度条提示框.DatePickerDialog日期选择对话框和TimePickerDialog时间选择对话框.这一节我们介绍几个新的API控件SwipeRefreshLayout.RecyclerView和CardView,这几个API控件都是google在Android5.0推出的.下面我们来学

我的编程之路(十九) 开发中一些细节与启发

1.js的命名空间           如果写后台代码,分层是潜意识中的基本常识,但是一到了前台,却没了这种意识,归根结底还是js用的不多,也一直没有在意js的地位,直到现在富客户端的趋势与要求,使得很多代码都要在前台用js或其框架完成,所以对于js代码的管理就要像后台java代码一样有其规范了,而命名空间就是package,也是为了管理不同层次的代码. 2.闭包          闭包就是能够读取其他函数内部变量的函数.它的最大用处有两个,一个是可以读取函数内部的变量,另一个就是让这些变量的值

《Javascript权威指南》学习笔记之十九--HTML5 DOM新标准---处理文档元信息和管理交互能力

一.了解DOM 1.DOM是Document Object Model的缩写,即文档对象类型,是文档在内存中的表示形式,是一个应用程序接口,定义了文档的逻辑结构以及一套访问和处理文档的方法. 2.HTML DOM与Core DOM的区别:前者提供了大量的方法和属性,与现有的程序模型一致,更便于脚本的编写者控制. 二.document对象 使用window.document属性返回一个document对象,代表当前window内加载的文档.window可以省略.winName.document返回

【Unity 3D】学习笔记二十九:游戏实例——简单小地图制作

任何的学习,光看不练是学不好的.所以这次就总结回顾下怎么制作MMROPG类游戏中的小地图.在MMROPG类游戏里,主角在游戏世界里走动时,一般在屏幕右上角都会有一个区域来显示当前游戏场景的小地图.主角在游戏世界里走动,小地图里代表着主角的小标记也会随之移动.那怎么实现咧? 首先需要确定两个贴图,第一个是右上角的小地图背景贴图,应该是从Y轴俯视向下截取主角所在的位置大地图.第二个就是主角的位置大贴图.在本例中,因为没有学习unity地图制作,所以地图用一个面对象代替,主角用立方体代替,使用GUI来

Android学习路线(十九)支持不同设备——支持不同(Android)平台版本

当最新的Android版本为你的应用提供着很棒的APIs时,你却要在更多的设备更新之前继续支持老的系统版本.这篇课程如何在继续支持低版本的系统的情况下使用新版本的高级API. Platform Versions 仪表板展示了最新的活跃设备上运行的Android系统版本的分布,基于设备访问Google Play商店的次数.通常情况下,支持90%的活跃设备同时使用最新版本作为target是一个好习惯. 贴士: 为了在不同的Android版本上提供最好的特性和功能,你应该在你的应用中使用Android

unity3d学习笔记(十九)--ngui制作3d人物头顶的头像和血条

原地址:http://blog.csdn.net/lzhq1982/article/details/18793479 本系列文章由Aimar_Johnny编写,欢迎转载,转载请标明出处,谢谢. http://blog.csdn.net/lzhq1982/article/details/18793479 先上张图,自己做的一个demo. 这里的人物头像和血条是在3d世界生成的,所以有真正的纵深感和遮挡关系,废话不多说,看我是怎么实现的. 第一步,先在UI Root里制作头像和血条. 这个制作步骤基

java痛苦学习之路[十二]JSON+ajax+Servlet JSON数据转换和传递

1.首先客户端需要引入 jquery-1.11.1.js 2.其次javaweb工程里面需要引入jar包  [commons-beanutils-1.8.0.jar.commons-collections-3.1.jar.commons-lang-2.4.jar.commons-logging-1.1.3.jar.ezmorph-1.0.6.jar.json-lib-2.3-jdk15.jar] 3.客户端js端代码 4.servlet 服务器,映射的路径CardColl 以上就是整个过程,如果

【WPF学习】第二十九章 元素绑定——将元素绑定到一起

原文:[WPF学习]第二十九章 元素绑定--将元素绑定到一起 数据banding的最简单情形是,源对象时WPF元素而且源属性是依赖性属性.前面章节解释过,依赖项属性具有内置的更改通知支持.因此,当在源对象中改变依赖项属性的值时,会立即更新目标对象中的绑定属性.这正是我们所需要的行为--而且不必为此构建任何额外的基础结构. 为理解如何将一个元素绑定到另一个元素,下面创建一个简单的示例.该示例窗口包含了两个控件:一个Slider控件和一个具有单行文本的TextBlock控件.如果向右拖动滑动条上的滑

【WPF学习】第十九章 控件类

原文:[WPF学习]第十九章 控件类 WPF窗口充满了各种元素,但这些元素中只有一部分是控件.在WPF领域,控件通常被描述为与用户交互的元素--能接收焦点并接受键盘或鼠标输入的元素.明显的例子包括文本框和按钮.然而,这个区别有时有些模糊.将工具提示视为控件,因为它根据用户鼠标的移动显示或消失.将标签视为控件,因为它支持记忆码(mnemonics,将焦点转移到相关控件快捷键). 所有控件都继承自System.Windows.Control类,该类添加了一小部分基本的基础结构: 设置控件内容对齐方式