Hadoop CombineTextInputFormat 切片机制

本文介绍如何优化Hadoop中大量小文件的处理效率,通过预处理合并文件或使用CombineTextInputFormat来减少MapTask数量,提高处理速度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于大量小文件的优化策略。

背景

默认情况下 TextInputformat 对任务的切片机制是按文件规划切片,不管文件多小,都会 是一个单独的切片,都会交给一个 maptask,这样如果有大量小文件,就会产生大量的 maptask, 处理效率极其低下。

优化

预处理

最好的办法,在数据处理系统的最前端(预处理/采集),将小文件先合并成大文 件,再上传到 HDFS 做后续分析。

CombineTextInputFormat

如果已经是大量小文件在 HDFS 中了,可以使用另一种 InputFormat 来做切片(CombineTextInputFormat),它的切片逻辑跟 TextFileInputFormat 不同:它可以将 多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个 maptask

优先满足最小切片大小,不超过最大切片大小 。

CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m CombineTextInputFormat.setMinInputSplitSize(job, 2097152);// 2m

举例:0.5m+1m+0.3m+5m=2m + 4.8m=2m + 4m + 0.8m

具体配置

// 如果不设置 InputFormat,它默认用的是 TextInputFormat.class 
job.setInputFormatClass(CombineTextInputFormat.class) 
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m 
CombineTextInputFormat.setMinInputSplitSize(job, 2097152);// 2m

Demo

准备了5个小文件,如下:

☁  CombineTextInputFormat  pwd
/Users/ylj/demo/input/CombineTextInputFormat
☁  CombineTextInputFormat  ll
total 19400
-rw-r--r--  1 ylj  staff   176K  4  7 15:35 flie1.txt
-rw-r--r--  1 ylj  staff   879K  4  7 15:39 flie2.txt
-rw-r--r--  1 ylj  staff   1.1M  4  7 15:39 flie3.txt
-rw-r--r--  1 ylj  staff   2.1M  4  7 15:41 flie4.txt
-rw-r--r--  1 ylj  staff   3.3M  4  7 15:42 flie5.txt

测试默认配置

-w1173

测试CombineTextInputFormat

仅设置setInputFormatClass
//设置InputFormat
job.setInputFormatClass(CombineTextInputFormat.class);

此时

SPLIT_MAXSIZE = Long.MAXValue
SPLIT_MINSIZE = 1

5个文件相加在此区间内,所以number of splits:1

-w1148

设置SPLIT_MAXSIZE、SPLIT_MINSIZE
//设置InputFormat
job.setInputFormatClass(CombineTextInputFormat.class);
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4m
CombineTextInputFormat.setMinInputSplitSize(job, 2097152);// 2m

此时
CombineTextInputFormat 切片机制

  1. 判断虚拟存储的文件大小是否大于setMaxInputSplitSize值,大于等于则单独形成一个切片;
  2. 如果不大于则跟下一个存储文件进行合并,共同形成一个切片。

-w1213

源码

文件:/org/apache/hadoop/mapreduce/lib/input/CombineFileInputFormat.java

if (maxSize == 0) {
    myLength = left;
} else {
    if (left > maxSize && left < 2 * maxSize) {
      // if remainder is between max and 2*max - then
      // instead of creating splits of size max, left-max we
      // create splits of size left/2 and left/2. This is
      // a heuristic to avoid creating really really small
      // splits.
      myLength = left / 2;
    } else {
      myLength = Math.min(maxSize, left);
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值