FileInputFormat切片源码解析
一、FileInputFormat切片机制
1.简单按照文件的内容长度进行切片
2.切片大小,默认等于Block大小
3.切片时不考虑数据集体性,而是针对每一个文件单独切片
二、切片过程
三、FileInputFormat切片大小配置参数
四、切片源码
//1、getSplits()方法源码解析:
long minSize = Math.max(getFormatMinSplitSize(), getMinSplitSize(job)); //切片最小值 1
getFormatMinSplitSize() //默认返回1
getMinSplitSize(job) //查看源码,返回0
//相关配置项【mapred-default.xml】:mapreduce.input.fileinputformat.split.minsize --0
long maxSize = getMaxSplitSize(job); //切片最大值 Long.MAX_VALUE
//相关配置项【mapred-default.xml】:mapreduce.input.fileinputformat.split.maxsize --无配置
List<InputSplit> splits = new ArrayList<InputSplit>();
List<FileStatus> files = listStatus(job); //获取存储文件的详情
for (FileStatus file: files) { //遍历files
if (ignoreDirs && file.isDirectory()) { //判断file是否是文件夹
continue;
}
Path path = file.getPath(); //获取文件路径
long length = file.getLen(); //获取文件长度
if (isSplitable(job, path)) { //判断文件是否可切分
long blockSize = file.getBlockSize(); //获取文件的块大小
//如果是集群环境,获取到的就是集群中设置的块大小,如果是本地环境,本地默认的块大小32M (33554432)
long splitSize = computeSplitSize(blockSize, minSize, maxSize); //计算切片大小
=查看computeSplitSize()方法=>return Math.max(minSize, Math.min(maxSize, blockSize));
}
long bytesRemaining = length; //文件的剩余大小
//只有当剩余文件大小 / 切片大下 其值 > 1.1 时,才会进行切片操作
while (((double) bytesRemaining)/splitSize > SPLIT_SLOP) { //计算切片时如何去切
int blkIndex = getBlockIndex(blkLocations, length-bytesRemaining);
splits.add(makeSplit(path, length-bytesRemaining, splitSize, //添加切片
blkLocations[blkIndex].getHosts(), //记录的是读取那个文件
blkLocations[blkIndex].getCachedHosts())); //从文件那个位置读取到那个位置
bytesRemaining -= splitSize; //按照块大小对剩余切片文件做减法运算
}
//最终将生成的切片放入到splits集合中.
结论:
1、如果剩余待切片的数据大小 除以 块大小,大于1.1 ,才会继续切片,如果不大于,则直接将剩余的数据
生成一个切片.
2、真实切片时,是完全按照块大小进行切的,只是针对剩余数据是否仍要切片时,会有一个大于1.1的判断,要做上述判断,避免生成很小的切片,节省MapTask资源
3、 切片大小默认等于Block大小128M,避免MR程序读取数据时,出现跨节点读取,节省资源。