(17)Hive ——MR任务的map与reduce个数由什么决定?

一、MapTask的数量由什么决定?

    MapTask的数量由以下参数决定

  • 文件个数
  • 文件大小
  • blocksize

 一般而言,对于每一个输入的文件会有一个map split,每一个分片会开启一个map任务,很容易导致小文件问题(如果不进行小文件合并,极可能导致Hadoop集群资源雪崩)

hive中小文件产生的原因及解决方案见文章:

(14)Hive调优——合并小文件-CSDN博客文章浏览阅读779次,点赞10次,收藏17次。Hive的小文件问题https://blog.csdn.net/SHWAITME/article/details/136108785

maxSize的默认值为256M,minSize的默认值是1byte切片大小splitSize的计算公式:

splitSize=Min(maxSize,Max(minSize,blockSize)) = Min(256M,Max(1 byte ,128M)) = 128M =blockSize

所以默认splitSize就等于blockSize块大小

# minSize的默认值是1byte
set mapred.min.split.size=1#maxSize的默认值为256M
set mapred.max.split.size=256000000#hive.input.format是用来指定输入格式的参数。决定了Hive读取数据时使用的输入格式,
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat

二、如何调整MapTask的数量

  假设blockSize一直是128M,且splitSize = blockSize = 128M。在不改变blockSize块大小的情况下,如何增加/减少mapTask数量

2.1 增加map的数量

      增加map:需要调小maxSize,且要小于blockSize才有效,例如maxSize调成100byte

      splitSize=Min(maxSize,Max(minSize,blockSize)) = Min(100,Max(1,128*1000*1000)) =100 byte = maxSize

   调整前的map数 = 输入文件的大小/ splitSize = 输入文件的大小/ 128M

   调整后的map数 = 输入文件的大小/ splitSize = 输入文件的大小/ 100byte

2.2 减少map的数量 

     减少map:需要调大minSize ,且要大于blockSize才有效,例如minSize 调成200M

      splitSize=Min(maxSize,Max(minSize,blockSize)) = Min(256m, Max(200M,128M)) = 200M=minSize

   调整前的map数 = 输入文件的大小/ splitSize = 输入文件的大小/ 128M

   调整后的map数 = 输入文件的大小/ splitSize = 输入文件的大小/ 200M

三、ReduceTask的数量决定

    reduce的个数决定hdfs上落地文件的个数(即: reduce个数决定文件的输出个数)。 ReduceTask的数量,由参数mapreduce.job.reduces 控制,默认值为 -1 时,代表ReduceTask的数量是根据hive的数据量动态计算的。

总体而言,ReduceTask的数量决定方式有以下两种:

3.1 方式一:hive动态计算

3.1.1 动态计算公式

 ReduceTask数量 = min (参数2,输入的总数据量/ 参数1)

参数1:hive.exec.reducers.bytes.per.reducer 

      含义:每个reduce任务处理的数据量(默认值:256M)

参数2:hive.exec.reducers.max 

     含义:每个MR任务能开启的reduce任务数的上限值(默认值:1009个)

ps: 一般参数2的值不会轻易变动,因此在普通集群规模下,hive根据数据量动态计算reduce的个数,计算公式为:输入总数据量/hive.exec.reducers.bytes.per.reducer

3.1.2 源码分析

(1)通过源码分析 hive是如何动态计算reduceTask的个数的?

	在org.apache.hadoop.hive.ql.exec.mr包下的 MapRedTask类中//方法类调用逻辑MapRedTask | ----setNumberOfReducers | ---- estimateNumberOfReducers|---- estimateReducers         

(2)核心方法setNumberOfReducers(读取 用户手动设置的reduce个数)

  /*** Set the number of reducers for the mapred work.*/private void setNumberOfReducers() throws IOException {ReduceWork rWork = work.getReduceWork();// this is a temporary hack to fix things that are not fixed in the compiler// 获取通过外部传参设置reduce数量的值 rWork.getNumReduceTasks() Integer numReducersFromWork = rWork == null ? 0 : rWork.getNumReduceTasks();if (rWork == null) {console.printInfo("Number of reduce tasks is set to 0 since there's no reduce operator");} else {if (numReducersFromWork >= 0) {//如果手动设置了reduce的数量 大于等于0 ,则进来,控制台打印日志console.printInfo("Number of reduce tasks determined at compile time: "+ rWork.getNumReduceTasks());} else if (job.getNumReduceTasks() > 0) {//如果手动设置了reduce的数量,获取配置中的值,并传入到work中int reducers = job.getNumReduceTasks();rWork.setNumReduceTasks(reducers);console.printInfo("Number of reduce tasks not specified. Defaulting to jobconf value of: "+ reducers);} else {//如果没有手动设置reduce的数量,进入方法if (inputSummary == null) {inputSummary =  Utilities.getInputSummary(driverContext.getCtx(), work.getMapWork(), null);}// #==========【重中之中】estimateNumberOfReducers int reducers = Utilities.estimateNumberOfReducers(conf, inputSummary, work.getMapWork(),work.isFinalMapRed());rWork.setNumReduceTasks(reducers);console.printInfo("Number of reduce tasks not specified. Estimated from input data size: "+ reducers);}//hive shell中所看到的控制台打印日志就在这里console.printInfo("In order to change the average load for a reducer (in bytes):");console.printInfo("  set " + HiveConf.ConfVars.BYTESPERREDUCER.varname+ "=<number>");console.printInfo("In order to limit the maximum number of reducers:");console.printInfo("  set " + HiveConf.ConfVars.MAXREDUCERS.varname+ "=<number>");console.printInfo("In order to set a constant number of reducers:");console.printInfo("  set " + HiveConf.ConfVars.HADOOPNUMREDUCERS+ "=<number>");}}

 (3)如果没有手动设置reduce的个数,hive是如何动态计算reduce个数的?

    int reducers = Utilities.estimateNumberOfReducers(conf, inputSummary, work.getMapWork(),work.isFinalMapRed());/*** Estimate the number of reducers needed for this job, based on job input,* and configuration parameters.** The output of this method should only be used if the output of this* MapRedTask is not being used to populate a bucketed table and the user* has not specified the number of reducers to use.** @return the number of reducers.*/public static int estimateNumberOfReducers(HiveConf conf, ContentSummary inputSummary,MapWork work, boolean finalMapRed) throws IOException {// bytesPerReducer 每个reduce处理的数据量,默认值为256M  BYTESPERREDUCER("hive.exec.reducers.bytes.per.reducer", 256000000L)long bytesPerReducer = conf.getLongVar(HiveConf.ConfVars.BYTESPERREDUCER);//整个mr任务,可以开启的reduce个数的上限值:maxReducers的默认值1009个MAXREDUCERS("hive.exec.reducers.max", 1009)int maxReducers = conf.getIntVar(HiveConf.ConfVars.MAXREDUCERS);//#===========对totalInputFileSize的计算double samplePercentage = getHighestSamplePercentage(work);long totalInputFileSize = getTotalInputFileSize(inputSummary, work, samplePercentage);// if all inputs are sampled, we should shrink the size of reducers accordingly.if (totalInputFileSize != inputSummary.getLength()) {LOG.info("BytesPerReducer=" + bytesPerReducer + " maxReducers="+ maxReducers + " estimated totalInputFileSize=" + totalInputFileSize);} else {LOG.info("BytesPerReducer=" + bytesPerReducer + " maxReducers="+ maxReducers + " totalInputFileSize=" + totalInputFileSize);}// If this map reduce job writes final data to a table and bucketing is being inferred,// and the user has configured Hive to do this, make sure the number of reducers is a// power of twoboolean powersOfTwo = conf.getBoolVar(HiveConf.ConfVars.HIVE_INFER_BUCKET_SORT_NUM_BUCKETS_POWER_TWO) &&finalMapRed && !work.getBucketedColsByDirectory().isEmpty();//#==============【真正计算reduce个数的方法】看源码的技巧return的方法是重要核心方法return estimateReducers(totalInputFileSize, bytesPerReducer, maxReducers, powersOfTwo);}                                                

(4) 动态计算reduce个数的方法 estimateReducers

	public static int estimateReducers(long totalInputFileSize, long bytesPerReducer,int maxReducers, boolean powersOfTwo) {double bytes = Math.max(totalInputFileSize, bytesPerReducer);// 假设totalInputFileSize 1000M// bytes=Math.max(1000M,256M)=1000Mint reducers = (int) Math.ceil(bytes / bytesPerReducer);//reducers=(int)Math.ceil(1000M/256M)=4  此公式说明如果totalInputFileSize 小于256M ,则reducers=1 ;也就是当输入reduce端的数据量特别小,即使手动设置reduce Task数量为5,最终也只会开启1个reduceTaskreducers = Math.max(1, reducers);//Math.max(1, 4)=4 ,reducers的结果还是4reducers = Math.min(maxReducers, reducers);//Math.min(1009,4)=4; reducers的结果还是4int reducersLog = (int)(Math.log(reducers) / Math.log(2)) + 1;int reducersPowerTwo = (int)Math.pow(2, reducersLog);if (powersOfTwo) {// If the original number of reducers was a power of two, use thatif (reducersPowerTwo / 2 == reducers) {// nothing to do} else if (reducersPowerTwo > maxReducers) {// If the next power of two greater than the original number of reducers is greater// than the max number of reducers, use the preceding power of two, which is strictly// less than the original number of reducers and hence the maxreducers = reducersPowerTwo / 2;} else {// Otherwise use the smallest power of two greater than the original number of reducersreducers = reducersPowerTwo;}}return reducers;}

3.2 方式二:用户手动指定

 手动调整reduce个数: set mapreduce.job.reduces = 10

 需要注意:出现以下几种情况时,手动调整reduce个数不生效。

3.2.1 order by 全局排序

   sql中使用了order by全局排序,那只能在一个reduce中完成,无论怎么调整reduce的数量都是无效的。

  hive (default)>set mapreduce.job.reduces=5;hive (default)> select * from empt order  by length(ename);Hadoop job information for Stage-1: number of mappers: 1; number of reducers: 1

3.2.2 map端输出的数据量很小

在【3.1.2 源码分析——(4) 】动态计算reduce个数的核心方法 estimateReducers中,有下面这三行代码:

int reducers = (int) Math.ceil(bytes / bytesPerReducer);
reducers = Math.max(1, reducers);
reducers = Math.min(maxReducers, reducers);

   如果map端输出的数据量bytes (假如只有1M) 远小于hive.exec.reducers.bytes.per.reducer (每个reduce处理的数据量默认值为256M) 参数值,maxReducers默认为1009个,计算下列值:

  int reducers  = (int) Math.ceil(1 / 256M)=1;reducers = Math.max(1, 1)=1;reducers = Math.min(1009, 1)=1;

  此时即使用户手动 set mapreduce.job.reduces=10,也不生效,reduce个数最后还是只有1个。

参考文章:

Hive mapreduce的map与reduce个数由什么决定?_hive中map任务和reduce任务数量计算原理-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/470569.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

干货 | 实战演练基于加密接口测试测试用例设计

如果接口测试仅仅只是掌握一些requests或者其他一些功能强大的库的用法&#xff0c;是远远不够的&#xff0c;还需要具有根据公司的业务以及需求去定制化一个接口自动化测试框架能力。所以在这个部分&#xff0c;会主要介绍接口测试用例分析以及通用的流程封装是如何完成的。 首…

蓝桥杯嵌入式学习记录——按键的使用

目录 一、按键原理简介 二、cubeMX的配置 三、按键的短按代码 四、按键的长按代码 一、按键原理简介 在STM32中&#xff0c;按键连接通常使用GPIO&#xff08;通用输入/输出&#xff09;端口来实现。当按键未被按下时&#xff0c;GPIO端口处于高电平状态&#xff08;即1&am…

应急响应实战笔记02日志分析篇(3)

第3篇:Web日志分析 ox01 Web日志 Web访问日志记录了Web服务器接收处理请求及运行时错误等各种原始信息。通过对WEB日志进行的安全分析&#xff0c;不仅可以帮助我们定位攻击者&#xff0c;还可以帮助我们还原攻击路径&#xff0c;找到网站存在的安全漏洞并进行修复。 我们来…

MySQL 基础知识(一)之数据库和 SQL 概述

目录 1 数据库相关概念 2 数据库的结构 ​3 SQL 概要 4 SQL 的基本书写规则 1 数据库相关概念 数据库是将大量的数据保存起来&#xff0c;通过计算机加工而成的可以进行高效访问的数据集合数据库管理系统&#xff08;DBMS&#xff09;是用来管理数据库的计算机系统&#xf…

ELAdmin 隐藏添加编辑按钮

使用场景 做了一个监控模块&#xff0c;数据都是定时生成的&#xff0c;所以不需要手动添加和编辑功能。 顶部不显示 可以使用 true 或者 false 控制现实隐藏 created() {this.crud.optShow {add: false,edit: false,del: true,download: true,reset: true}},如果没有 crea…

如何手机搜学法减分答案? #媒体#职场发展

今天分享拥有拍照搜题、文字搜题、语音搜题、多重搜题等搜题模式&#xff0c;可以快速查找问题解析&#xff0c;加深对题目答案的理解。 1.证件照全能管家&#xff08;APP&#xff09; 一个非常好用的证件照APP 常用的证件照尺寸和底色都有、日常的证件照编辑完全够用&#…

gem5 garnet 合成流量: packet注入流程

代码流程 下图就是全部. 剩下文字部分是细节补充,但是内容不变: bash调用python,用python配置好configuration, 一个cpu每个tick运行一次,requestport发出pkt. bash 启动 python文件并配置 ./build/NULL/gem5.debug configs/example/garnet_synth_traffic.py \--num-cpus…

456. 车站分级(拓扑排序,虚拟点建图)

活动 - AcWing 一条单向的铁路线上&#xff0c;依次有编号为 1, 2, …, n1,  的 n 个火车站。 每个火车站都有一个级别&#xff0c;最低为 1 级。 现有若干趟车次在这条线路上行驶&#xff0c;每一趟都满足如下要求&#xff1a;如果这趟车次停靠了火车站 x&#xff0c;…

事务及在SpringBoot项目中使用的两种方式

1.事务简介 事务&#xff08;transaction&#xff09;是访问并可能操作各种数据项的一个数据库操作序列&#xff0c;这些操作要么全部执行&#xff0c;要么全部不执行&#xff0c;是一个不可分割的工作单位。 事物的四大特性: 原子性&#xff08;Atomicity&#xff09;&#xf…

OLED显示红外遥控键码

基本原理 本遥控器的编码是NEC编码&#xff0c;为PWM&#xff08;脉冲宽度调制&#xff09;。 发射红外载波的时间固定&#xff0c;通过改变不发射载波的时间来改变占空比。 逻辑“0”是由0.56ms的38KHZ载波和0.560ms的无载波间隔组成&#xff1b;逻辑“1”是由0.56ms的38KHZ…

【JAVA】计算机软件工程人工智能研究生复试资料整理

1、JAVA 2、计算机网络 3、计算机体系结构 4、数据库 5、计算机租场原理 6、软件工程 7、大数据 8、英文 自我介绍 1. Java 1. == 和 equals的区别 比较基本数据类型是比较的值,引用数据类型是比较两个是不是同一个对象,也就是引用是否指向同 一个对象,地址是否相同,equ…

代码随想录算法训练营第51天 | 139.单词拆分 + 多重背包理论基础 + 背包问题总结

今日任务 139.单词拆分 关于多重背包&#xff0c;你该了解这些&#xff01; 背包问题总结篇&#xff01; 139.单词拆分 - Medium 题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 给你一个字符串 s 和一个字符串列表 wordDict …