MapReduce任务个数如何影响执行效率?性能优化从这里做起

在正文开始之前,请先来回答一下这个问题:

bash 复制代码
题目:输入为3个文件,a.txt 300MB,b.txt 100MB,c.txt 58.MB,使用MapReduce的example程序,计算Wordcount,请问,应该有多少个MapTask?

A、5       B、4       C、3       D、2

这是一个MR知识点中非常简单的一个问题,其中涉及到的知识点大概如下:

1.HDFS Block拆分,为啥是128MB

HDFS选择将数据块的默认大小设置为128MB,有以下几个原因:

1.减少元数据开销:较大的数据块大小可以减少元数据(metadata)的数量,因为元数据存储了文件的信息,如文件名、权限和数据块的位置等。较小的数据块会导致更多的元数据,增加了管理和存储的开销。

2.提高数据传输效率:较大的数据块可以提高数据传输的效率。在Hadoop集群中,数据块是以流的方式进行传输的,较大的数据块可以减少寻址和传输的开销,提高数据的读取和写入速度。

3.适应大规模数据处理:HDFS主要用于大规模数据处理,如大数据分析和批处理作业。较大的数据块可以更好地适应这些大规模数据处理需求,减少了数据切分和处理的开销。

2.MR对于输入数据的拆分

在 MapReduce 中,Map 操作的输入拆分格式取决于使用的输入格式。以下是常见的输入拆分格式:

1.TextInputFormat:将输入拆分为按行划分的文本块。每个 Map 任务处理一行或多行文本。

2.KeyValueTextInputFormat:类似于 TextInputFormat,但将每行拆分为键值对。键和值之间使用分隔符进行分割。

3.SequenceFileInputFormat:将输入拆分为 SequenceFile 格式的块。SequenceFile 是一种二进制文件格式,可存储键值对。

4.NLineInputFormat:将输入拆分为固定数量的行块。每个 Map 任务处理一块。

5.CombineTextInputFormat:将小文件组合成更大的输入拆分块,以减少 Map 任务的数量。这样可以提高作业的整体性能。

这些输入拆分格式的选择取决于输入数据的特性和处理需求。可以根据具体的情况选择合适的输入拆分格式来优化 Map 操作的性能。

以上都是大家在各个平台所能看到的理论答案,直接拿出来给大家做科普,那就太没诚意了。我们今天就来点实操性的,实践出真知。

1.Map Task个数验证

根据以上题目内容,咋们来制造一波测试数据集,按照题目设定,搞来三个文件,分别大小如下:

bash 复制代码
[root@bigdata input]# du -h *
299M  a.txt
100M  b.txt58M   c.txt

数据来源说明:下载的是《西游记》电子txt版,单个文件大概是3MB左右,然后使用追加的方式累计文件中。

我们将这个数据上传到HDFS,运行一波看看,这个有多少个Map个数。

bash 复制代码
#数据上传到DHFS
hdfs dfs -put input /apps/mapreduce/#运行测试命令hadoop jar ./hadoop-mapreduce-examples-3.3.4.jar    \wordcount    \/apps/mapreduce/input    \/apps/mapreduce/output

运行结果结果如下图展示,其中Map个数为5,Reduce为1,所以,开头的答案是A,请问,您答对了吗?

下图是使用Yarn UI2 看到的页面,这样更直观知道每个task任务的执行流程。

接下来,你是不是觉得我应该写:为啥是5,为啥是1呢?恭喜您,猜错了,还是太年轻,这东西值得我拿出来在公众号做分享吗,会被其他同行看不起的。咋们要讲,就要讲实际能用的,和工作相关的。

2.存储结构对比验证

在实际工作中,遇上题目这种a、b、c的情况比较少,但是分析一个???MB左右的数据却经常遇到。接下来分析一个同样的458MB的"文件",但是这里的文件存储结构是3MB * 153个,那么又会发生这么样的故事呢?

数据准备:将我们准备好的单个3MB的文件,循环copy并编号1-153,输入到input2文件夹。简单的shell,大家自己脑补下,毕竟,这不是今天的重点。完成后的数据格式如下:

接下来上传数据,运行测试案例

#数据上传到DHFS

bash 复制代码
hdfs dfs -put input2 /apps/mapreduce/#运行测试命令hadoop jar ./hadoop-mapreduce-examples-3.3.4.jar    \wordcount    \/apps/mapreduce/input2    \/apps/mapreduce/output2

毫无意外,这次运行,明显慢了很多,运行的结果情况如下:

UI2任务流程图:

对比两次任务执行时间,第一次为:33s,第二次为139s,同样的大小的数据,居然差了4.21倍。这是啥概念?如果不是很明白,那就换个说法,加大点时间,老板让你去写个分析SQL,别人上午写,下午出结果,而你,上午写,让他明天等结果...,那么恭喜你,你在老板的小本本里面了。

你以为这就完了,NO,因为在实际企业中,没几个正常人写MR,都是些SQL,那么我们来看看,同样分析458MB的数据,A(a、b、c存储法),B(3 mb * 153存储法)两种存储结构,带来的花销是一样的吗?

3.Hive分区中结构对比实验

接下来,我们就使用同样的SQL,分析同样大小的数据,但是因为存储结构的不同,给运行带来的影响。

首先,创建一个实验表:

bash 复制代码
--创建表:
CREATE EXTERNAL TABLE IF NOT EXISTS `student.student0`(  `id` string comment '学号',  `name` string comment '姓名',  `sex` string comment '性别',  `age` int comment '年龄',  `department` string comment '班级')  partitioned by(dt string)  ROW FORMAT DELIMITED FIELDS TERMINATED BY '|'  LINES TERMINATED BY '\n';

验证下数据存储情况:

bash 复制代码
--插入数据:
insert into student.student0 values ("965","maoshu.ran","男",18,"Shanghai","2023-06-27");

--查看数据信息与存储结构:
hdfs dfs -get /warehouse/tablespace/external/hive/student.db/student0/dt=2023-06-27/000000_0--查看数据内容:965|maoshu.ran|男|18|Shanghai

接下来,我们就按上面的存储结构"965|maoshu.ran|男|18|Shanghai"制造一波测试案例数据。经过测试,大概75000条数据存储为3MB。我们先生成单个3MB文件,在批量叠加。

bash 复制代码
#单个3MB数据生产
for i in {0..75000}; do echo "20230627`printf "%06d\n" $i`|maoshu.ran|男|18|Shanghai">>000000_0.txt; done#创建数据集存储目录mkdir dt=2023-06-27mkdir dt=2023-06-28#数据集A制作cat 000000_0.txt >>dt=2023-06-27/000000_0.txtcat 000000_0.txt >>dt=2023-06-27/000000_0.txt...
#数据集B制作
sed s/20230627/20230628/g -i 000000_1.txtfor i in {1..157}; do cp 000000_1.txt dt\=2023-06-28/000000_$i.txt; done

最后整个目录结构和文件结构如下:

将数据上传到hive数据目录,并确认数据是否能够读取到。

bash 复制代码
#数据上传到hdfs
hdfs dfs -put dt\=2023-06-27 /warehouse/tablespace/external/hive/student.db/student0hdfs dfs -put dt\=2023-06-28 /warehouse/tablespace/external/hive/student.db/student0/#刷新hive分区(到hive命令行中)MSCK REPAIR TABLE student0;
> show partitions student0;
OK
dt=2023-06-27
dt=2023-06-28

接下来,写SQL验证,太难的SQL,笔者不会写,因为"懒",我们就写最简单的count(*)

测试结果前,确认下输入模式:

确认下输入格式:

bash 复制代码
Hive> set hive.input.formathive.input.format=org.apache.hadoop.hive.ql.io.CombineHiveInputFormat;

发现,默认使用的是CombineHiveInputFormat,看来HIVE很有先见之明啊。我们先用这个模式跑下验证

进行场景A验证

select count(*) from student0 where dt='2023-06-27';

其运行的流程图如下:3个Map,1个reduce,总执行时间是:39.959s

进行场景B验证

select count(*) from student0 where dt='2023-06-28';47.341

执行时间是47.341s,使用了Combine模式,这个Task个数,明显小于153,效果还是很明显的。但是很明显,执行时间和task个数均比场景A多。

接下来,我们切换为MR中默认的TextInputFormat看看

bash 复制代码
set hive.input.format=org.apache.hadoop.mapred.TextInputFormat;

运行统计命令如上,其结果有点飘

场景A运行情况

场景B运行情况

虽然运行情况不太如愿,但是也能看出来,情景B的Task个数,明显多于场景A。

4.总结

在我们的整个验证过程中, Hive中的SQL演示,在日常的数据分析工作中是很常见的。同样的SQL,同样规模数据,为啥运行时间不一样?可能并不是因为你写的SQL有问题,不妨思考下,会不会是底层存储的问题

所以,课后作业来了:HDFS 小文件会带来哪些影响?

相关推荐
大霸王龙1 小时前
软件工程的软件生命周期通常分为以下主要阶段
大数据·人工智能·旅游
点赋科技2 小时前
沙市区举办资本市场赋能培训会 点赋科技分享智能消费新实践
大数据·人工智能
YSGZJJ2 小时前
股指期货技术分析与短线操作方法介绍
大数据·人工智能
Doker 多克2 小时前
Flink CDC —部署模式
大数据·flink
异常君2 小时前
高并发数据写入场景下 MySQL 的性能瓶颈与替代方案
java·mysql·性能优化
Guheyunyi2 小时前
监测预警系统重塑隧道安全新范式
大数据·运维·人工智能·科技·安全
Channing Lewis3 小时前
如果科技足够发达,是否还需要维持自然系统(例如生物多样性)中那种‘冗余’和‘多样性’,还是可以只保留最优解?
大数据·人工智能·科技
禺垣3 小时前
区块链技术概述
大数据·人工智能·分布式·物联网·去中心化·区块链
IvanCodes4 小时前
七、Sqoop Job:简化与自动化数据迁移任务及免密执行
大数据·数据库·hadoop·sqoop