首先要知道两个概念:
数据块:Block是HDFS物理上把数据分成一块一块。
数据切片:数据切片只是在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。
MapTask的并行度决定Map阶段的任务处理并发度,进而影响到整个Job的处理速度,而每个切片都会分配给一个MapTask进行处理,但却不是并行MapTask数越多越快(思考:1G的数据,启动8个MapTask,可以提高集群的并发处理能力。那么1K的数据,也启动8个MapTask,会提高集群性能吗?MapTask并行任务是否越多越好呢?哪些因素影响了MapTask并行度?)
再要理解一点就是,切片机制会参考block块大小来设置(方便资源的io调度),但不会受制于block的物理存储位置,因为分片的行为针对的基本单位是文件
FileInputFormat:
机制:
1.如果不设置切片大小,切片的默认值大小为block块大小
2.按照文件内容长度顺序切片
3.不考虑数据集整体,针对各个文件进行切片
(和block分块存储时的规则基本一致,稍有不同的是如果剩余未分片的部分不大于分片值得1.1倍则会看作一片)
例子:
此时若有个130M的文件,则它会被分配为第五个切片(130/128 未超过1.1)
CombineTextInputFormat:
应用场景:框架默认的TextInputFormat切片机制是对任务按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个MapTask,这样如果有大量小文件,就会产生大量的MapTask,处理效率极其低下,CombineTextInputFormat用于小文件过多的场景,它可以将多个小文件从逻辑上规划到一个切片中,这样,多个小文件就可以交给一个MapTask处理。
机制:
一.设置一个虚拟文件最大值,之后开始虚拟化存储文件,形成一分一分的虚拟文件:
1.设置虚拟文件最大值:CombineTextInputFormat.setMaxInputSplitSize(job, 4194304);// 4M,虚拟存储切片最大值设置 可以根据实际的小文件大小情况来设置具体的值。
2.切片过程
(1)虚拟存储过程:
将输入目录下所有文件大小,依次和设置的setMaxInputSplitSize值比较,如果不大于设置的最大值,逻辑上划分一个块。如果输入文件大于设置的最大值且大于两倍,那么以最大值切割一块;当剩余数据大小超过设置的最大值且不大于最大值2倍,此时将文件均分成2个虚拟存储块(防止出现太小切片)。
例如setMaxInputSplitSize值为4M,输入文件大小为8.02M,则先逻辑上分成一个4M。剩余的大小为4.02M,如果按照4M逻辑划分,就会出现0.02M的小的虚拟存储文件,所以将剩余的4.02M文件切分成(2.01M和2.01M)两个文件。
(2)切片过程:
(a)判断虚拟存储的文件大小是否大于setMaxInputSplitSize值,大于等于则单独形成一个切片。
(b)如果不大于则跟下一个虚拟存储文件进行合并,共同形成一个切片。
(c)测试举例:有4个小文件大小分别为1.7M、5.1M、3.4M以及6.8M这四个小文件,则虚拟存储之后形成6个文件块,大小分别为:
1.7M,(2.55M、2.55M),3.4M以及(3.4M、3.4M)
最终会形成3个切片,大小分别为:
(1.7+2.55)M,(2.55+3.4)M,(3.4+3.4)M