1.1分片的概念
MapReduce在进行作业提交时,会预先对将要分析的原始数据进行划分处理,形成一个个等长的逻辑数据对象,称之为输入分片(inputSplit),简称“分片”。MapReduce为每一个分片构建一个单独的MapTask,并由该任务来运行用户自定义的map方法,从而处理分片中的每一条记录。
1.2分片大小的选择
- 拥有许多分片,意味着处理每个分片所需要的时间要小于处理整个输入数据所花的时间(分而治之的优势)。
- 并行处理分片,且每个分片比较小。负载平衡,好的计算机处理的更快,可以腾出时间,做别的任务
- 如果分片太小,管理分片的总时间和构建map任务的总时间将决定作业的整个执行时间。
- 如果分片跨越两个数据块,那么分片的部分数据需要通过网络传输到map任务运行的节点,占用网络带宽,效率更低
- 因此最佳分片大小应该和HDFS上的块大小一致。hadoop2.x默认128M.
提问:为什么片是128M呢,或者说为什么128M是最佳分片呢,为什么不能大于128或者小于128?
答:
- 为了跟块保证一样的大小,这样保证整体的效率更高。
- 当切的比块更大的时候,肯定会出现跨块的情况,如果两个块儿正好不在同一台机器上时,肯定出现跨服务器的情况,从而导致大量网络资源的占用,提升网络IO的压力,降低程序的通信效率。
- 如果说一个机器里有十个maptask,当切得切的片过大时,会导致所以文件数据可能都被切到一片里,也就意味着占用了一个maptask,这就相当于,让其他的资源浪费了,同时也意味着这个maptask的工作时间会很长,任务完成时间会很长。
- 因为现在我们所用的是千兆网卡. 而千兆网卡的传输速率普遍是 100M/s,所以,将片大小设置为128M最佳。
- 因为一个片对应一个Maptask,如果切的片过于的小,那么当对一个文件进行分片处理时,就会产生许多的片,同时也会生成许多的Maptask,而对于每台机器来说,他的资源是有限的,而用资源的不仅仅是这一个应用,是所有应用共享资源,而如果maptask过多,便会导致资源的浪费。而我们知道启动maptask肯定是需要花费时间的,但如果说处理片的时间比启动maptask的时间都小,这样肯定是不合理的。
1.3对于分片的总结
1.3.1分片大小参数
通过分析源码,在FileInputFormat中,计算切片大小的逻辑:Math.max(minSize, Math.min(maxSize, blockSize)); 切片主要由这几个值来运算决定。
参数 | 默认值 | 属性 |
---|---|---|
minsize | 1 | mapreduce.input.fileinputformat.split.minsize |
maxsize | Long.MAXVALUE | mapreduce.input.fileinputformat.split.maxsize |
blocksize | 块大小 | dfs.blocksize: |
可以看出,就是取minsize、maxsize、blocksize三者的中间的那个值。
- 将maxsize调得比blocksize小,则会让切片变小,而且就等于配置的这个参数的值.
- 将minsize调得比blockSize大,则会让切片变得比blocksize还大
- 但是,不论怎么调参数,都不能让多个小文件"划入"一个split
1.3.2创建过程总结
-
获取文件大小及位置
-
判断文件是否可以分片(压缩格式有的可以进行分片,有的不可以)
-
获取分片的大小
-
剩余文件的大小/分片大小>1.1时,循环执行封装分片信息的方法,具体如下:
封装一个分片信息(包含文件的路径,分片的起始偏移量,要处理的大小,分片包含的块的信息,分片中包含的块存在哪儿些机器上) -
剩余文件的大小/分片大小<=1.1且不等于0时,封装一个分片信息(包含文件的路径,分片的起始偏移量,要处理的大小,分片包含的块的信息,分片中包含的块存在哪儿些机器上)
1.3.3分片细节问题总结
如果有多个分片
- 第一个分片读到末尾再多读一行
- 既不是第一个分片也不是最后一个分片第一行数据舍弃,末尾多读一行
- 最后一个分片舍弃第一行,末尾多读一行
- 为什么:前一个物理块不能正好是一行结束的位置啊
1.3.4分片与块的区别
- 分片是逻辑数据,记录的是要处理的物理块的信息而已
- 块是物理的,是真实存储在文件系统上的原始数据文件。