文件切片
-
什么是切片
数据块(Block):HDFS中数据保存的单位,HDFS在物理上将数据分为一个一个Block管理
数据切片(Split):在逻辑上对Map任务输入数据的切片。 -
为什么要切片
将输入文件分为多片可以并行进行Map阶段的计算,提高Job的运行速度。一份数据切片就会有一个MapTask。 -
文件的切片机制 决定如何对数据文件进行切片,进而决定了一个MapReduce任务有多少个并行的MapTask
简单的按照文件的内容长度切片,切片大小默认为Block的大小(128M),但每次切片完都会判断剩下的部分是否大于块的1.1倍,不大于1.1倍就归入上一个切片,数据切片只是对一个数据文件在逻辑上对输入进行分片,并不会在磁盘上将其切分成片进行存储。数据切片是MapReduce程序计算输入数据的单位,一个切片会对应启动一个MapTask。
切片时不会考虑数据集整体,而是单独针对每一份文件切片(默认)。
一个完整的MapReduce程序包括四个阶段:Map Task阶段、Shuffle阶段、Reduce Task阶段
InputFormat发生在MapTask之前。数据由InputFormat来负责进行切分和读取,然后将读取到的数据交给MapTask处理,所以InputFormat读取出来的数据是什么类型,MapTask接收的数据就是什么类型. 所以InputFormat是mapreduce处理数据的第一步,它接触的是最原始的数据文件,将原始数据处理成KV形式交给Mapper处理;
InputFormat是一个抽象类,用于获取Input输入数据,并将其切分和打成<k,v>键值对;这个类中有两个抽象方法,源码如下:
public abstract class InputFormat<K, V> {
public InputFormat() {
}
public abstract List<InputSplit> getSplits(JobContext var1) throws IOException, InterruptedException;
public abstract RecordReader<K, V> createRecordReader(InputSplit var1, TaskAttemptContext var2) throws IOException, InterruptedException;
}
(1)getSplits:负责将HDFS数据解析成InputSplit,也就是对原始数据进行切片,按照设定的切片大小进行逻辑切片;InputSplit只记录了切片的元数据信息,例如偏移量的起止位置、长度和所在节点列表等。决定如何对数据文件进行切片,进而决定了一个MapReduce任务有多少个并行的MapTask
(2)createRecordReader:获取每个InputSplit,并且将其中的每一行解析成<k,v>键值对。
FileInputFormat中默认的切片机制
切片的大小=块的大小=128M(如果程序运行在本地则是32M)切片的标准是看文件大的小是达到块大小的1.1倍(140.8M),如果达到则按128M进行切片,如果没达到,则其本身就是一个切片。切完第一片剩下的数据在进行比较,如果达到块大小的1.1被,依然按照128M切片,不够则本身为一个切片,以此类推。CombineTextInputFormat切片机制关于大量小文件的优化策略:默认情况下FileInputformat对任务的切片机制是按文件规划切片,不管文件多小,都会是一个单独的切片,都会交给一个maptask,这样如果有大量小文件,就会产生大量的maptask,处理效率极其低下
- 切片时不考虑数据集整体,而是逐个针对每一一个文件单独切片
比如
1、MapReduce输入路径下假如有两个文件,分别是a.txt为320M, b.txt为10M大小
2、则经过FileInputFormat切片后产生的切片信息如下:
// 总产生4个切片,文件a有3个切片,文件b有1个切片
a.txt的切片1: 0~128M
a.txt的切片2: 128~256M
a.txt的切片3: 256~320M
b.txt的切片1: 0~10M
在MapReduce中,如果不指定,那么默认使用是TextInputFormat,而TextInputFormat继承了FileInputFormat。默认情况下,FileInputFormat负责对文件进行切片处理;TextInputFormat负责提供输入流来读取数据。
FileInputFormat在对文件进行切片过程中的注意问题:
a. 切片最小是1个字节大小,最大是Long.MAX_VALUE。
b. 如果是一个空文件,则整个文件作为一个切片来进行处理。
c. 在MapReduce中,文件存在可切与不可切的问题。大多数情况下,默认文件是可切的;但是如果是压缩文件,则不一定可切。
d. 如果文件不可切,无论文件多大,都作为一个切片来进行处理。
e. 在MapReduce中,如果不指定,Split和Block等大。
f. 如果需要调小Split,那么需要调小maxSize;如果需要调大Split,那么需要调大minSize。
g. 在切片过程中,需要注意阈值SPLIT_SLOP=1.1。
5. TextInputFormat在读取数据过程中需要注意的问题:
TextInputFormat在对文件进行处理之前,会先判断文件是否可切:先获取文件的压缩编码,然后判断压缩编码是否为空。如果压缩编码为空,则说明该文件不是压缩文件,那么默认可切;如果压缩编码不为空,则说明该文件是一个压缩文件,会判断这是否是一个可切的压缩文件。
在MapReduce中,默认只有BZip2(.bz2)压缩文件可切。
从第二个MapTask开始,会从当前切片的第二行开始处理,处理到下一个切片的第一行;第一个MapTask要多处理一行数据;最后一个MapTask要少处理一行数据。这样做的目的是为了保证数据的完整性。