今天总结本人在使用Hive过程中的一些优化技巧,希望给大家带来帮助。Hive优化最体现程序员的技术能力,面试官在面试时最喜欢问的就是Hive的优化技巧。

技巧1.控制reducer数量

下面的内容是我们每次在hive命令行执行SQL时都会打印出来的内容:

In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=<number>
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=<number>
In order to set a constant number of reducers:
set mapreduce.job.reduces=<number>

很多人都会有个疑问,上面的内容是干什么用的。我们一一来解答,先看

set hive.exec.reducers.bytes.per.reducer=<number>,这个一条Hive命令,用于设置在执行SQL的过程中每个reducer处理的最大字节数量。可以在配置文件中设置,也可以由我们在命令行中直接设置。如果处理的数据量大于number,就会多生成一个reudcer。例如,number = 1024K,处理的数据是1M,就会生成10个reducer。我们来验证下上面的说法是否正确:

  1. 执行set hive.exec.reducers.bytes.per.reducer=200000;命令,设置每个reducer处理的最大字节是200000。
  2. 执行sql:
select user_id,count(1) as cnt
from orders group by user_id limit 20;

执行上面的sql时会在控制台打印出信息:

  Number of reduce tasks not specified. Estimated from input data size: 159
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=<number>
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=<number>
In order to set a constant number of reducers:
set mapreduce.job.reduces=<number>
Starting Job = job_1538917788450_0020, Tracking URL = http://hadoop-master:8088/proxy/application_1538917788450_0020/
Kill Command = /usr/local/src/hadoop-2.6.1/bin/hadoop job -kill job_1538917788450_0020
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 159

控制台打印的信息中第一句话:Number of reduce tasks not specified. Estimated from input data size: 159。翻译成中文:没有指定reducer任务数量,根据输入的数据量估计会有159个reducer任务。然后在看最后一句话:number of mappers: 1; number of reducers: 159。确定该SQL最终生成159个reducer。因此如果我们知道数据的大小,只要通过set hive.exec.reducers.bytes.per.reducer命令设置每个reducer处理数据的大小就可以控制reducer的数量。

接着看
set hive.exec.reducers.max=<number> 这也是一条Hive命令,用于设置Hive的最大reducer数量,如果我们设置number为50,表示reducer的最大数量是50。
我们来验证下这个说法是否正确:

  1. 执行命令set hive.exec.reducers.max=8;设置reducer的数量为8。
  2. 继续执行sql:
select user_id,count(1) as cnt
from orders group by user_id limit 20;

会在控制台打印出如下信息:

Number of reduce tasks not specified. Estimated from input data size: 8
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=<number>
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=<number>
In order to set a constant number of reducers:
set mapreduce.job.reduces=<number>
Starting Job = job_1538917788450_0020, Tracking URL = http://hadoop-master:8088/proxy/application_1538917788450_0020/
Kill Command = /usr/local/src/hadoop-2.6.1/bin/hadoop job -kill job_1538917788450_0020
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 8

控制台打印的信息中第一句话:Number of reduce tasks not specified. Estimated from input data size: 8。reducer的数据量为8,正好验证了我们的说法。set set hive.exec.reducers.max=8;命令是设置reducer的数量的上界。

最后来看set mapreduce.job.reduces=<number>命令。这条Hive命令是设置reducer的数据,在执行sql会生成多少个reducer处理数据。使用和上面同样的方法来验证set mapreduce.job.reduces=这条命令。

  1. 执行命令set mapreduce.job.reduces=5;设置reducer的数量为8。
  2. 继续执行sql:
select user_id,count(1) as cnt
from orders group by user_id limit 20;

会在控制台打印出如下信息:

Number of reduce tasks not specified. Defaulting to jobconf value of: 5
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=<number>
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=<number>
In order to set a constant number of reducers:
set mapreduce.job.reduces=<number>
Starting Job = job_1538917788450_0026, Tracking URL = http://hadoop-master:8088/proxy/application_1538917788450_0026/
Kill Command = /usr/local/src/hadoop-2.6.1/bin/hadoop job -kill job_1538917788450_0026
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 5

根据Number of reduce tasks not specified. Defaulting to jobconf value of: 5和number of mappers: 1; number of reducers: 5这两句话,可以知道生成5个reducer。

如果我们将数量由5改成15。还是执行select user_id,count(1) as cnt
from orders group by user_id limit 20;SQL,在控制台打印的信息是:

Launching Job 1 out of 1
Number of reduce tasks not specified. Defaulting to jobconf value of: 15
In order to change the average load for a reducer (in bytes):
set hive.exec.reducers.bytes.per.reducer=<number>
In order to limit the maximum number of reducers:
set hive.exec.reducers.max=<number>
In order to set a constant number of reducers:
set mapreduce.job.reduces=<number>
Starting Job = job_1538917788450_0027, Tracking URL = http://hadoop-master:8088/proxy/application_1538917788450_0027/
Kill Command = /usr/local/src/hadoop-2.6.1/bin/hadoop job -kill job_1538917788450_0027
Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 15

可见reducer的数量已经由5变为15个。

小结,控制hive中reducer的数量由三种方式,分别是:

set hive.exec.reducers.bytes.per.reducer=<number>
set hive.exec.reducers.max=<number>
set mapreduce.job.reduces=<number>

其中set mapreduce.job.reduces=<number>的方式优先级最高,set hive.exec.reducers.max=<number>优先级次之,set hive.exec.reducers.bytes.per.reducer=<number> 优先级最低。从hive0.14开始,一个reducer处理文件的大小的默认值是256M。

reducer的数量并不是越多越好,我们知道有多少个reducer就会生成多少个文件,小文件过多在hdfs中就会占用大量的空间,造成资源的浪费。如果reducer数量过小,导致某个reducer处理大量的数据(数据倾斜就会出现这样的现象),没有利用hadoop的分而治之功能,甚至会产生OOM内存溢出的错误。使用多少个reducer处理数据和业务场景相关,不同的业务场景处理的办法不同。

技巧2.使用Map join

sql中涉及到多张表的join,当有一张表的大小小于1G时,使用Map Join可以明显的提高SQL的效率。如果最小的表大于1G,使用Map Join会出现OOM的错误。
用法:

select /*+ MAPJOIN(table_a)*/,a.*,b.* from table_a a join table_b b on a.id = b.id

技巧3.使用distinct + union all代替union

如果遇到要使用union去重的场景,使用distinct + union all比使用union的效果好。
distinct + union all的用法:

select count(distinct *)
from (
select order_id,user_id,order_type from orders where order_type='0' union all
select order_id,user_id,order_type from orders where order_type='1' union all
select order_id,user_id,order_type from orders where order_type='1'
)a;

union的用法:

select count(*)
from(
select order_id,user_id,order_type from orders where order_type='0' union
select order_id,user_id,order_type from orders where order_type='0' union
select order_id,user_id,order_type from orders where order_type='1')t;

技巧4.解决数据倾斜的通用办法

数据倾斜的现象:任务进度长时间维持在99%,只有少量reducer任务完成,未完成任务数据读写量非常大,超过10G。在聚合操作是经常发生。
通用解决方法:set hive.groupby.skewindata=true;
将一个map reduce拆分成两个map reduce。

说说我遇到过的一个场景,需用统计某个一天每个用户的访问量,SQL如下:

select t.user_id,count(*) from user_log t group by t.user_id

执行这条语句之后,发现任务维持在99%达到一个小时。后面自己分析user_log表,发现user_id有很多数据为null。user_id为null的数据会有一个reducer来处理,导致出现数据倾斜的现象。解决方法有两种:
1、通过where条件过滤掉user_id为null的记录。
2、将为null的user_id设置一个随机数值。保证所有数据平均的分配到所有的reducer中处理。

转载自:https://www.cnblogs.com/airnew/p/9808514.html

Hive 调优的更多相关文章

  1. 【Hive六】Hive调优小结

    Hive调优 Hive调优 Fetch抓取 本地模式 表的优化 小表.大表Join 大表Join大表 MapJoin Group By Count(Distinct) 去重统计 行列过滤 动态分区调整 ...

  2. 【Hive】Hive笔记:Hive调优总结——数据倾斜,join表连接优化

    数据倾斜即为数据在节点上分布不均,是常见的优化过程中常见的需要解决的问题.常见的Hive调优的方法:列剪裁.Map Join操作. Group By操作.合并小文件. 一.表现 1.任务进度长度为99 ...

  3. Hive调优笔记

    Hive调优 先记录了这么多,日后如果有遇到,再补充. fetch模式 <property> <name>hive.fetch.task.conversion</name ...

  4. (转) hive调优(2)

    hive 调优(二)参数调优汇总 在hive调优(一) 中说了一些常见的调优,但是觉得参数涉及不多,补充如下 1.设置合理solt数 mapred.tasktracker.map.tasks.maxi ...

  5. (转)hive调优(1) coding调优

    hive 调优(一)coding调优 本人认为hive是很好的工具,目前支持mr,tez,spark执行引擎,有些大公司原来封装的sparksql,开发py脚本,但是目前hive支持spark引擎(不 ...

  6. hive 调优(二)参数调优汇总

    在hive调优(一) 中说了一些常见的调优,但是觉得参数涉及不多,补充如下 1.设置合理solt数 mapred.tasktracker.map.tasks.maximum 每个tasktracker ...

  7. 【Hadoop离线基础总结】Hive调优手段

    Hive调优手段 最常用的调优手段 Fetch抓取 MapJoin 分区裁剪 列裁剪 控制map个数以及reduce个数 JVM重用 数据压缩 Fetch的抓取 出现原因 Hive中对某些情况的查询不 ...

  8. Hive调优相关

    前言 Hive是由Facebook 开源用于解决海量结构化日志的数据统计,是基于Hadoop 的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提供类 SQL查询功能. 在资源有限的情况下,提 ...

  9. hive 调优手段

    调优手段 ()利用列裁剪 当待查询的表字段较多时,选取需要使用的字段进行查询,避免直接select *出大表的所有字段,以免当使用Beeline查询时控制台输出缓冲区被大数据量撑爆. ()JOIN避免 ...

  10. Hive调优

    Hive存储格式选择 和Hive 相关优化: 压缩参考 Hive支持的存储数的格式主要有:TEXTFILE .SEQUENCEFILE.ORC.PARQUET. 文件存储格式 列式存储和行式存储 行存 ...

随机推荐

  1. Linux+QT界面开发(含数据库)小结

    今天十一国庆节,过了一个很有意义的国庆节,去了龙岗区图书馆,第一次知道了借的书可以在任意分馆归还!这个切实方便了广大读者.针对Linux应用,特意借阅一本:<linux环境下Qt4图形界面与My ...

  2. iOS核心动画(专用图层篇)

    之前的文章我们了解了Core Animation中图层的一些基础知识.没有看过的传送门在此: iOS核心动画基础篇 那么在了解了这些基础知识之后,接下来进入专用图层的了解 苹果为了方便和性能,封装了几 ...

  3. Springboot+Quartz+MySql整合页面版

    目的: springboot整合Quartz 连接mysql整合出页面版 springboot整合Quartz 新建一个springboot项目来 导入pom依赖 <?xml version=& ...

  4. 组件系列之RabbitMQ

    官网: https://www.rabbitmq.com/getstarted.html 1.四种交换机 TODO... 2.消费者获取消息方式:推 和 拉 拉取:每次拉取一条,循环拉取需要的条数在批 ...

  5. shell 学习笔记9-while/until循环语句

    一.while循环语句 1.循环语句 循环愈久就是重复执行一条指令或一组执行,知道条件不在满足时停止,shell循环语句包括,while.until.for.select语句 2.while循环 主要 ...

  6. 配置APP的图标

    https://www.cnblogs.com/hupo376787/p/10290840.html 上一篇文章说到  Flutter - 自动生成Android & iOS图标 通过flut ...

  7. React Native 开发豆瓣评分(四)集中管理 fetch 数据请求

    豆瓣评分的API接口 接口是从网上查找的,看样子应该是微信小程序里面扣出来的(ua 里面有 wechatdevtools) 接口都需要设置apiKey(054022eaeae0b00e0fc068c0 ...

  8. 阅读笔记---第三章 Xen信息页

    1.文件/xen/include/public/xen.h 2.第一个数据结构:启动信息页strat_info,启动信息页是GuestOS内核启动时,由Xen映射到GusetOS内存空间的一个物理页面 ...

  9. kafka环境安装及简单使用(单机版)

    一个分布式发布-订阅消息传递系统 特点: 高吞吐量.低延迟 使用场景(举例): 日志收集:用kafka收集各种服务产生的log,通过kafka以统一的接口服务的方式开放给各种consumer,如had ...

  10. VIM的配置以及插件管理

    VIM的配置详细说明参考:http://www.ruanyifeng.com/blog/2018/09/vimrc.html 此外VIM的插件管理比如 Vundle可以参考这个博客: https:// ...