今天总结本人在使用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. Appium移动端自动化测试--录制测试用例并运行

    目录 文章目录如下 录制用例并执行 1.使用Appium desktop录制用例 2.安装Pythony依赖Appium-Python-Client 3.增加隐式等待增强稳定性 4.重新运行 文章目录 ...

  2. Linux 总结篇

    1. sudo -i update upgrade install 包名 (openjdk-8-jdk) autoremove 自动删除不需要的包(remove卸载) sudo apt-get 2. ...

  3. vue中$router与$route的区别

    $.router是VueRouter的实例,相当于一个全局的路由器对象.包含很多属性和子对象,例如history对象 $.route表示当前正在跳转的路由对象.可以通过$.route获取到name,p ...

  4. 访问Harbor报502 Bad Gateway

    Harbor启动都是多个容器的,首先查看一下是否有相关容器未启动 docker ps | grep harbor cae340214e57 goharbor/nginx-photon:v1.9.3 & ...

  5. Centos 7系统在线安装docker

    在线安装docker 以下操作步骤均在root用户下操作 1. 检查内核是否符合要求 Docker 要求 Centos系统的内核版本高于 3.10 ,建议在Centos 7版本命令如下: uname ...

  6. JavaNetty

    Netty的简单使用: import io.netty.bootstrap.Bootstrap; import io.netty.buffer.Unpooled; import io.netty.ch ...

  7. ITIL《信息技术基础架构库》

    一 概述 1. ITIL 自上世纪70年代开始,个人计算机以及计算机网络开始在欧美发达国家普及.随着时间的推移,信息系统的规模越来越大,人们对信息系统的依赖也越来越强.特别是到了80年代,互联网开始普 ...

  8. Golang-使用md5对字符串进行加密

    方式一: func md5Test1(str string) string { m5 := md5.New() _,err := m5.Write([]byte(str)) if err != nil ...

  9. vue element-ui el-date-picker如何限制选择时间为当天之前

    <el-date-picker  v-model="firstdate"  :picker-options="pickerOptions0"  type= ...

  10. 仿EXCEL插件,智表ZCELL产品V1.6 版本发布,增加自定义事件功能

    详细请移步 智表(ZCELL)官网www.zcell.net 更新说明  这次更新主要应用户要求,主要解决了单元格值变化时事件的支持,并新增了按单元格名操作的相关API,欢迎大家体验使用. 本次版本更 ...