热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何在Hive中合理配置Map和Reduce任务数量以优化不同场景下的性能表现

在Hive中合理配置Map和Reduce任务的数量对于优化不同场景下的性能至关重要。本文探讨了如何控制Hive任务中的Map数量,分析了当输入数据超过128MB时是否会自动拆分,以及Map数量是否越多越好的问题。通过实际案例和实验数据,本文提供了具体的配置建议,帮助用户在不同场景下实现最佳性能。

设置map和reduce的个数

  • 一、控制hive任务中的map数:
    • 如果超过128m就一定会被拆分吗?
    • 是不是map数越多越好?
      • 那么针对这种情况,如何合并小文件,减少map数?
    • 是不是保证每个map处理接近128m的文件块,就高枕无忧了?
      • 那么针对这种情况,如何适当增加map数?
  • 二、 控制hive任务的reduce数:
    • reduce个数多好还是少好?
    • 如何调整reduce个数?
    • 什么情况下只有一个reduce?


一、控制hive任务中的map数:
  • 通常情况下,作业会通过input的目录产生一个或者多个map任务。
  • 主要的决定因素有: input的文件总个数,input的文件大小,集群设置的文件块大小(目前为128M, 可在hive中通过set dfs.block.size;命令查看到,该参数不能自定义修改);
  • 举例:
    • a) 假设input目录下有1个文件a,大小为780M,那么hadoop会将该文件a分隔成7个块(6个128m的块和1个12m的块),从而产生7个map数。
    • b) 假设input目录下有3个文件a,b,c,大小分别为10m,20m,150m,那么hadoop会分隔成4个块(10m,20m,128m,22m),从而产生4个map数
    • 如果文件大于块大小(128m),那么会拆分,如果小于块大小,则把该文件当成一个块。

如果超过128m就一定会被拆分吗?


  • 不一定
  • 如果是130m,仍然只会产生1个map
  • 允许有10%的溢出:如果文件大小超过分片大小10%以内,作为一个分片
    • 设计目的:避免一个MapTask处理的数据太小
  • 具体原因可以参考这篇文章

是不是map数越多越好?


  • 答案是否定的。
  • 如果一个任务有很多小文件(远远小于块大小128m),则每个小文件也会被当做一个块,用一个map任务来完成,而一个map任务启动和初始化的时间远远大于逻辑处理的时间,就会造成很大的资源浪费。而且,同时可执行的map数是受限的。

那么针对这种情况,如何合并小文件,减少map数?


  • 假设一个SQL任务:

Select count(1)
from xxx
where pt =2020-08-11;

  • 该表的分区目录下共有194个文件,其中很多是远远小于128m的小文件,总大小9G,正常执行会用194个map任务。
  • 可以通过以下方法来在map执行前合并小文件,减少map数:
  • 方式1:输入合并,即在Map前合并小文件,下面的数值需自行调整


set hive.hadoop.supports.splittable.combineinputformat=true;
-- 执行map前进行小文件合并
set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;
set mapred.min.split.size=100000000;
set mapred.max.split.size=100000000;
-- 一个节点上split的至少的大小 ,决定了多个data node上的文件是否需要合并
set mapred.min.split.size.per.node=50000000;
-- 一个交换机下split的至少的大小,决定了多个交换机上的文件是否需要合并
set mapred.min.split.size.per.rack=50000000;

  • 解释
    • 100000000表示100M
    • set hive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;这个参数表示执行前进行小文件合并
    • 过期的对应配置可以查询:https://hadoop.apache.org/docs/stable/hadoop-project-dist/hadoop-common/DeprecatedProperties.html
    • mapred.min.split.size相当于mapreduce.input.fileinputformat.split.minsize,设置哪一个都一样
    • mapred.max.split.size相当于mapreduce.input.fileinputformat.split.maxsize,设置哪一个都一样
    • 所以根据求splitSize的公式,return Math.max(minSize, Math.min(maxSize, blockSize));
    • 可以知道,需增加mapper数,则减少这些值;需减少mapper数,则增加这些值,一般就配置这两个值就行了
    • 一般来说
      • max.split.size >= min.split.size >= min.size.per.node >= min.size.per.node
    • 优先级
      • 当四个参数设置矛盾时,系统会自动以优先级最高的参数为准,进行计算
      • max.split.size <&#61; min.split.size <&#61; min.size.per.node <&#61; min.size.per.node
  • 方式2&#xff1a;结果合并,下面的数值需自行调整

set hive.merge.mapfiles&#61;true; --Map-only的任务结束时合并小文件
set hive.merge.mapredfiles&#61;true; --Map-Reduce的任务结束时合并小文件
set hive.merge.size.per.task&#61;128000000; --合并后文件的大小为128M左右
set hive.merge.smallfiles.avgsize&#61;128000000; --当输出文件的平均大小小于128M时&#xff0c;启动一个独立的map-reduce任务进行文件merge

  • Hive在对结果文件进行合并时会执行一个额外的map-only脚本&#xff0c;mapper的数量是文件总大小除以size.per.task参数所得的值

是不是保证每个map处理接近128m的文件块&#xff0c;就高枕无忧了&#xff1f;


  • 答案也是不一定。
  • 比如有一个127m的文件&#xff0c;正常会用一个map去完成&#xff0c;但这个文件只有一个或者两个小字段&#xff0c;却有几千万的记录&#xff0c;如果map处理的逻辑比较复杂&#xff0c;用一个map任务去做&#xff0c;肯定也比较耗时

那么针对这种情况&#xff0c;如何适当增加map数&#xff1f;


  • 当input的文件都很大&#xff0c;任务逻辑复杂&#xff0c;map执行非常慢的时候&#xff0c;可以考虑增加Map数&#xff0c;来使得每个map处理的数据量减少&#xff0c;从而提高任务的执行效率。
  • 假设有这样一个任务&#xff1a;

Select data_desc,
count(1),
count(distinct id),
sum(case when …),
sum(case when …),
sum()
from a group by data_desc

  • 如果表a只有一个文件&#xff0c;大小为120M&#xff0c;但包含几千万的记录&#xff0c;如果用1个map去完成这个任务&#xff0c;肯定是比较耗时的&#xff0c;这种情况下&#xff0c;我们要考虑将这一个文件合理的拆分成多个&#xff0c;这样就可以用多个map任务去完成。

set mapred.reduce.tasks&#61;10;

  • map的最终个数取决于goalsize&#61;min(totalsize/mapred.reduce.tasks,块大小),goalsize就相当于splitsize
  • 但是往往这个是不生效的
    • 如果hive处理的文件是压缩模式&#xff0c;且压缩模式不支持文件切分&#xff0c;那么这个时候我们只能通过控制参数来减少map个数&#xff0c;而不能通过配置参数来增加map个数&#xff0c;所以Hive对于压缩不可切分文件的调优有限
  • 那么我们可以利用中间表

create table a_1 as
select * from a
distribute by CAST(RAND() *10 AS INT);

  • 这样会将a表的记录&#xff0c;随机的分散到包含10个文件的a_1表中&#xff0c;再用a_1代替上面sql中的a表&#xff0c;则会用10个map任务去完成。每个map任务处理大于12M&#xff08;几百万记录&#xff09;的数据&#xff0c;效率肯定会好很多。
  • 看上去&#xff0c;貌似这两种有些矛盾&#xff0c;一个是要合并小文件&#xff0c;一个是要把大文件拆成小文件&#xff0c;这点正是重点需要关注的地方&#xff0c;根据实际情况&#xff0c;控制map数量需要遵循两个原则&#xff1a;使大数据量利用合适的map数&#xff1b;使单个map任务处理合适的数据量

二、 控制hive任务的reduce数&#xff1a;
  • Hive自己如何确定reduce数&#xff1a;
    • reduce个数的设定极大影响任务执行效率&#xff0c;不指定reduce个数的情况下&#xff0c;Hive会猜测确定一个reduce个数&#xff0c;基于以下两个设定&#xff1a;
    • hive.exec.reducers.bytes.per.reducer&#xff08;每个reduce任务处理的数据量&#xff0c;默认为1000^3&#61;1G&#xff09;
    • hive.exec.reducers.max&#xff08;每个任务最大的reduce数&#xff0c;默认为999&#xff09;
    • 计算reducer数的公式很简单N&#61;min(参数2&#xff0c;总输入数据量/参数1)
      即&#xff0c;如果reduce的输入&#xff08;map的输出&#xff09;总大小不超过1G,那么只会有一个reduce任务&#xff1b;
    • 例如下图&#xff0c;(67108864/1024/1024&#61;64m),可以推测一个130m的输入数据量会启动reducer数&#61;min&#xff08;1099&#xff0c;130m/64m&#xff09;&#61;3个reduce
      在这里插入图片描述

reduce个数多好还是少好?


  • 同map一样&#xff0c;启动和初始化reduce也会消耗时间和资源&#xff1b;
  • 另外&#xff0c;有多少个reduce,就会有多少个输出文件&#xff0c;如果生成了很多个小文件&#xff0c;那么如果这些小文件作为下一个任务的输入&#xff0c;则也会出现小文件过多的问题&#xff1b;

如何调整reduce个数?


  • 调整reduce个数方法一&#xff1a;
    • 调整hive.exec.reducers.bytes.per.reducer参数的值&#xff1b;
    • 500000000即&#xff08;500M&#xff09;

set hive.exec.reducers.bytes.per.reducer&#61;500000000;

  • 调整reduce个数方法二&#xff1b;

set mapred.reduce.tasks &#61; 15;

什么情况下只有一个reduce&#xff1f;


  • 很多时候你会发现任务中不管数据量多大&#xff0c;不管你有没有设置调整reduce个数的参数&#xff0c;任务中一直都只有一个reduce任务&#xff1b;其实只有一个reduce任务的情况&#xff0c;除了数据量小于hive.exec.reducers.bytes.per.reducer参数值的情况外&#xff0c;还有以下原因&#xff1a;
    • a) 没有group by的汇总
      • 比如把select pt,count(1) from table_xxx where pt &#61; &#39;2020-08-11&#39; group by pt; 写成 select count(1) from table_xxx where pt &#61; &#39;2020-08-11&#39;;
    • b) 用了Order by
    • c) 有笛卡尔积
  • 通常这些情况下&#xff0c;除了找办法来变通和避免&#xff0c;我暂时没有什么好的办法&#xff0c;因为这些操作都是全局的&#xff0c;所以hadoop不得不用一个reduce去完成&#xff1b;
  • 同样的&#xff0c;在设置reduce个数的时候也需要考虑这两个原则&#xff1a;使大数据量利用合适的reduce数&#xff1b;使单个reduce任务处理合适的数据量

推荐阅读
  • 在稀疏直接法视觉里程计中,通过优化特征点并采用基于光度误差最小化的灰度图像线性插值技术,提高了定位精度。该方法通过对空间点的非齐次和齐次表示进行处理,利用RGB-D传感器获取的3D坐标信息,在两帧图像之间实现精确匹配,有效减少了光度误差,提升了系统的鲁棒性和稳定性。 ... [详细]
  • 深入解析Gradle中的Project核心组件
    在Gradle构建系统中,`Project` 是一个核心组件,扮演着至关重要的角色。通过使用 `./gradlew projects` 命令,可以清晰地列出当前项目结构中包含的所有子项目,这有助于开发者更好地理解和管理复杂的多模块项目。此外,`Project` 对象还提供了丰富的配置选项和生命周期管理功能,使得构建过程更加灵活高效。 ... [详细]
  • 本文详细解析了 MySQL 5.7.20 版本中二进制日志(binlog)崩溃恢复机制的工作流程。假设使用 InnoDB 存储引擎,并且启用了 `sync_binlog=1` 配置,文章深入探讨了在系统崩溃后如何通过 binlog 进行数据恢复,确保数据的一致性和完整性。 ... [详细]
  • 本文深入探讨了 MXOTDLL.dll 在 C# 环境中的应用与优化策略。针对近期公司从某生物技术供应商采购的指纹识别设备,该设备提供的 DLL 文件是用 C 语言编写的。为了更好地集成到现有的 C# 系统中,我们对原生的 C 语言 DLL 进行了封装,并利用 C# 的互操作性功能实现了高效调用。此外,文章还详细分析了在实际应用中可能遇到的性能瓶颈,并提出了一系列优化措施,以确保系统的稳定性和高效运行。 ... [详细]
  • openGauss行存储核心架构及其页面组织详解
    行存储的核心架构和页面组织是实现DML操作、可见性判断及多种管理功能的基础。作为基于磁盘的存储引擎,行存储在设计上采用了段页式结构,以优化数据的存储和访问效率。这种设计不仅确保了数据的高效存储,还为行存储的各种高级功能提供了坚实的技术支持。 ... [详细]
  • 题目描述:小K不幸被LL邪教洗脑,洗脑程度之深使他决定彻底脱离这个邪教。在最终离开前,他计划再进行一次亚瑟王游戏。作为最后一战,他希望这次游戏能够尽善尽美。众所周知,亚瑟王游戏的结果很大程度上取决于运气,但通过合理的策略和算法优化,可以提高获胜的概率。本文将详细解析洛谷P3239 [HNOI2015] 亚瑟王问题,并提供具体的算法实现方法,帮助读者更好地理解和应用相关技术。 ... [详细]
  • Go语言实现Redis客户端与服务器的交互机制深入解析
    在前文对Godis v1.0版本的基础功能进行了详细介绍后,本文将重点探讨如何实现客户端与服务器之间的交互机制。通过具体代码实现,使客户端与服务器能够顺利通信,赋予项目实际运行的能力。本文将详细解析Go语言在实现这一过程中的关键技术和实现细节,帮助读者深入了解Redis客户端与服务器的交互原理。 ... [详细]
  • 本文介绍了一种简化版的在线购物车系统,重点探讨了用户登录和购物流程的设计与实现。该系统通过优化界面交互和后端逻辑,提升了用户体验和操作便捷性。具体实现了用户注册、登录验证、商品浏览、加入购物车以及订单提交等功能,旨在为用户提供高效、流畅的购物体验。 ... [详细]
  • JVM参数设置与命令行工具详解
    JVM参数配置与命令行工具的深入解析旨在优化系统性能,通过合理设置JVM参数,确保在高吞吐量的前提下,有效减少垃圾回收(GC)的频率,进而降低系统停顿时间,提升服务的稳定性和响应速度。此外,本文还将详细介绍常用的JVM命令行工具,帮助开发者更好地监控和调优JVM运行状态。 ... [详细]
  • MySQL:不仅仅是数据库那么简单
    MySQL不仅是一款高效、可靠的数据库管理系统,它还具备丰富的功能和扩展性,支持多种存储引擎,适用于各种应用场景。从简单的网站开发到复杂的企业级应用,MySQL都能提供强大的数据管理和优化能力,满足不同用户的需求。其开源特性也促进了社区的活跃发展,为技术进步提供了持续动力。 ... [详细]
  • 深入解析:RKHunter与AIDE在入侵检测中的应用与优势
    本文深入探讨了RKHunter与AIDE在入侵检测领域的应用及其独特优势。通过对比分析,详细阐述了这两种工具在系统完整性验证、恶意软件检测及日志文件监控等方面的技术特点和实际效果,为安全管理人员提供了有效的防护策略建议。 ... [详细]
  • 第五章详细探讨了 Red Hat Enterprise Linux 6 中的 Ext3 文件系统。5.1 节介绍了如何创建 Ext3 文件系统,包括必要的命令和步骤,以及在实际操作中可能遇到的问题和解决方案。此外,还涵盖了 Ext3 文件系统的性能优化和维护技巧,为用户提供全面的操作指南。 ... [详细]
  • 表面缺陷检测数据集综述及GitHub开源项目推荐
    本文综述了表面缺陷检测领域的数据集,并推荐了多个GitHub上的开源项目。通过对现有文献和数据集的系统整理,为研究人员提供了全面的资源参考,有助于推动该领域的发展和技术进步。 ... [详细]
  • Linux磁盘管理入门指南:MBR分区格式详解与安装步骤
    在 CentOS 7.x 环境下,本文详细介绍了 MBR 分区格式的基本概念及其安装步骤。实验中使用了 SAS 和 SATA 硬盘,其中 SAS 硬盘主要用于企业级应用和服务器,而 SATA 硬盘则广泛应用于个人计算机和低端服务器。文章通过具体操作示例,帮助读者更好地理解和掌握 Linux 磁盘管理的基本技能。 ... [详细]
  • MySQL 数据操作:增、删、查、改全面解析
    MySQL 数据操作:增、删、查、改全面解析 ... [详细]
author-avatar
Graceedelweiss_602
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有