HDFS读取数据分区的数量

今天认真的看了看RDD 的分区,感觉挺麻烦的,就在此记录总结一下,如果有错误,还请各位大神指出!

在我们使用并行化的方式创建sparkRDD的时候,我们可以指定RDD的分区。

我们知道,mapreduce读取文件时允许的最小分区是1,而spark允许的最小分区是2

hdfs读取文件时,默认会根据输入文件数量创建多少个task,生成对应数量的切片(文件小于blocksize).

首先查看一下hdfs上面的文件信息:
在这里插入图片描述
可以看到,一共有三个文件,它们的大小分别是6b,6b,684b.都小于一个blocksize(128m)。

接着创建一个RDD:
在这里插入图片描述
此时它产生了4个逻辑切片。

我们再创建一次RDD,这次指定分区数量为1:
在这里插入图片描述
这时我们看到它产生了3个逻辑切片。

经过查看源码,发现hdfs在进行分区切片的时候定义了新的规则:
首先我们跟踪textFile的源码:
在这里插入图片描述
在这里插入图片描述
从这里我们可以看出他定义的minPartitions(最小分区数量)是2。然后下面创建了一个hadoopFile,将这个最小的分区数量作为参数。

然后查看hadoopFile,
在这里插入图片描述
在这里创建了HadoopRDD,同时将这个最小分区数量传了进去。
在HadoopRDD这个类中,定义了构造器:
在这里插入图片描述
创建完了之后,返回这个RDD。

在启动任务之前,会记录一下要启动多少task,所以在创建完HadoopRDD后,决定要启动多少task,然后开始执行(触发action),将task在driver端生成,调度到excutor端执行。

继续跟踪源码,在执行action时,他会去调用一个方法,getPartitions(HadoopRDD上定义的一个抽象方法):

在这里插入图片描述
这里val inputSplits = inputFormat.getSplits(jobConf,minPartitions)将minpartitins传进去了,而minpartitions的值为2.

接着往下执行:
在这里插入图片描述
这里totalSize是要读取文件的总长度。计算时会先把文件的总长度读取出来。
numSplits是我们可以自定义传入的分区数,它的默认值是2.
然后它用totalSize除以numSplits得到一个goalSize(目标长度)

下面就开始切分了:
在这里插入图片描述
用一个computeSplitSize方法计算怎么切分:

在这里插入图片描述
这里可以看出,他计算的方法就是在goalSize和blockSize中取出最小值,再跟minSize(最小是1b)比较,取出最大值当作切分的大小。

切完之后,会判断剩余文件的大小:

在这里插入图片描述
拿着剩下文件的大小除以splitSize(刚刚计算出来的切分长度),得到的结果如果大于SPLIT_SLOP,就继续切,如果小于这个值,就不再切分了。SPLIT_SLOP的默认值是1.1

总结:

1.上面就是hdfs计算每个切片大小的规则,但是这值是逻辑上的切分,只是记录了切分的偏移量,并不是真的这样切。
但是,这样处理是有好处的,因为每个文件的大小是不确定的,这样更加的灵活,可以尽量保证每个分区上切片一样大。
2.如果有的文件很小,就像上面的例子,我们不希望他再切分了,我们可以将它的最小分区数量设为1:

val rdd = sc.textFile("hdfs://L1:9000/wc",1)

3.如果要读取的文件个数为1,而这个文件很小(小于blockSize),而且设置最小分区数量为1的时候,那么他最后产生的分区数量就是1,如果指定最小分区数量为2,那么他最后产生的分区数量为2.

也就是说,当读取的文件数为n,而且每个文件都是小于blockSize的,那么当设置最小分区数量为1的时候,他最后产生的分区数量就是n。

但是为什么有多少个文件最后就产生多少个分区呢,是因为hdfs中mapreduce在执行时,有多少个map就产生多少个切片。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值