CombineTextInputFormat
org.apache.hadoop.mapreduce.lib.input
包下的 CombineTextInputFormat
是 同包下的 CombineFileInputFormat
类 的实现类
而 CombineFileInputFormat
类,才是 FileInputFormat
的实现类
所以我们这里说的是 FileInputFormat
的实现类的实现类。
框架默认的 TextInputFormat
切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下。
应用场景
CombineTextInputFormat
用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个 MapTask 处理。
虚拟存储切片设置最大值
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304) // 4MB
虚拟存储切片最大值设置最好根据实际的小文件大小情况来设置具体的值
注意:这里设置的是虚拟存储切片,并不是实际的切片大小。
切片机制
生成切片过程包括:虚拟存储过程
和 切片过程
两部分
例如现在有a、b、c、d四个文件,它们的大小分别是1.7M、5.1M、3.4M、6.8M
虚拟存储过程
将输入目录下所有文件大小,依次和设置的setMaxInputSplitSize 值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。
例如 setMaxInputSplitSize 值为4M,输入文件大小为8.02M,则先逻辑上分成一个4M。剩余的大小为 4.02M,如果按照4M 逻辑划分,就会出现0.02M的小的虚拟存储文件,所以将剩余的4.02M 文件切分成(2.01M和2.01M)两个文件。
拿上面的4MB举例子,这里的虚拟存储过程如下:
a文件大小1.7M 小于 4M,划分一块
b文件大小5.1M 大于 4M 但是 小于 24M,划分两块,每块2.55M
c文件大小3.4M 小于 4M,划分一块
d文件大小6.8M 大于 4M 但是 小于 24M,划分两块,每块3.4M
切片过程
- 判断虚拟存储的文件大小是否大于
setMaxInputSplitSize
值,大于等于则单独形成一个切片。 - 如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片
所以这里最终会形成三个切片:(1.7 + 2.55)M、(2.55 + 3.4)M、(3.4 + 3.4)M
注意
注意:这里整合切片的顺序不是按照从小到大合并的,而是在一开始文件排序、进入虚拟存储过程后,进行合并的
(a)判断虚拟存储的文件大小是否大于 setMaxInputSplitSize 值,大于等于则单独形成一个切片。←
(b)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。“(c)测试举例:有 4个小文件大小分别为 1.7M、5.1M、3.4M 以及 6.8M 这四个小
案例
依照前面的示例,进行改动,共改变了三部分,这里不进行赘述
- 设置实现类
// 设置实现类
job.setInputFormatClass(CombineFileInputFormat.class);
- 设置虚拟存储切片
// 设置虚拟存储切片
CombineTextInputFormat.setMaxInputSplitSize(job, 4194304) // 4MB
- 准备对应的文件,改变输入文件地址(地址可以为文件夹)