1.用sc.parallelize()生成RDD
默认分区数:sc.parallelize(collection)
指定分区数:sc.parallelize(collection,2)
2.用sc.textFile()生成RDD (分区数与文件数量有关)
默认分区数:sc.textFile(“hdfs://xxx”)
指定分区数:sc.textFile(“hdfs://xxx”,3)
最小分区数: minPartitions: Int = defaultMinPartitions
情况一:如果sc.textFile方法中未指定最小分区数(minPartitions),系统将会取默认defaultMinPartitions,def defaultMinPartitions: Int = math.min(defaultParallelism, 2),defaultMinPartitions不会大于2,其中defaultParallelism会对结果产生影响,而defaultParallelism对应的方法是override def defaultParallelism(): Int =
scheduler.conf.getInt(“spark.default.parallelism”, totalCores),能影响defaultParallelism的值的参数是配置参数"spark.default.parallelism"和totalCores,totalCores是可以在程序中指定的,如上代码中关于local[2]的介绍,这里就是defaultMinPartitions的确定
情况二:如果在textFile方法中指定minPartitions,那么最小分区数就是指定的值
分片数:
主要步骤是得到splitSize,然后循环文件列表,按文件大小进行分片,最后得到的真实分片数量可能会大于numSplits(minPartitions),其中需要注意的是:
① 流式文件不支持分片,也就是全部分成一块
② splitSize的大小确定, long splitSize = computeSplitSize(goalSize, minSize, blockSize),其中
long goalSize = totalSize / (numSplits == 0 ? 1 : numSplits),long blockSize = file.getBlockSize()取的是配置文件中配置的块大小
③ 文件分片时,溢出比例SPLIT_SLOP=1.1,((double) bytesRemaining)/splitSize > SPLIT_SLOP,意思是如果1.0 <(最后剩余文件内容/分片大小)<1.1就将剩下的所有内容分到一个分区上
④ 如果内容长度为0L也会分一片
注:inputFormat.getSplits(jobConf, minPartitions)是rdd.partitions触发的
getSplits()的源码:
/** Splits files returned by {@link #listStatus(JobConf)} when
* they're too big.*/
public InputSplit[] getSplits(JobConf job, int numSplits)
throws IOException {
StopWatch sw = new StopWatch().start();
FileStatus[] files = listStatus(job);
// Save the number of input files for metrics/loadgen
job.setLong(NUM_INPUT_FILES, files.length);
long totalSize = 0; // compute total size
for (FileStatus file: files) {
// check we have valid files
if (file.isDirectory()) {
throw new