def textFile(
path: String,
minPartitions: Int = defaultMinPartitions): RDD[String] = withScope {
assertNotStopped()
hadoopFile(path, classOf[TextInputFormat], classOf[LongWritable], classOf[Text],
minPartitions).map(pair => pair._2.toString).setName(path)
}
1.参数:第一个参数表示读取的路径
第二个参数表示最小分区数量,默认值为: math.min(defaultParallelism, 2)
2.文件切片规则 : 以字节方式来切片
查看defaultParallelism代码可以找到
override def defaultParallelism(): Int =
scheduler.conf.getInt("spark.default.parallelism", totalCores)
def getInt(key: String, defaultValue: Int): Int = catchIllegalValue(key) {
getOption(key).map(_.toInt).getOrElse(defaultValue)
}
由上面代码可以发现:defaultParallelism的值是先去获取配置spark.default.parallelism的值,如果没有则为当前启动的spark运行环境的总核数tatalCores
然而实际产生的分区数量可能大于最小分区数,取决于总的字节数是否能整除分区数并且剩余的字节达到一个比率
3. 数据读取规则 :以行为单位来读取
Spark读取文件采用的是Hadoop的读取规则
3.1 读文件,sc.textFile("input/w.txt", 4),这里使用@@表示换行符,换行符占两个字节
数据存储结构 | offset |
1@@ | 012 |
2@@ | 345 |
3@@ | 678 |
4 | 9 |
分区数计算 = 最小分区数 + (总字节数 % 最小分区数) / ( 总字节数/最小分区数 ) > 0.1 ? 1 : 0
= 4 + (10%4) / (10/4) > 0.1 ? 1 : 0
= 4 + 2 / 2 > 0.1 ? 1 : 0 = 5
分区 | offset范围 | 读取到的数据 |
1 | (0, 0+2) | 1 |
2 | (2, 2+2) | 2 |
3 | (4, 4+2) | 3 |
4 | (6, 6+2) | |
5 | (8,8+2) | 4 |
3.2. 读目录:sc.textFile("input/files", 3)
hadoop分区是以文件为单位进行划分的。读取数据不能跨越文件
文件 | 数据存储结构 | offset |
1.txt | 1@@ | 012 |
234 | 345 |
文件 | 数据存储结构 | offset |
2.txt | 1@@ | 012 |
234 | 345 |
分区数计算 = 3 + (12%3) / (12/3) > 0.1 ? 1 : 0 = 3
文件 | 分区 | offset范围 | 数据 |
1.txt | 1 | (0, 0+4) | 1 234 |
2 | (4,4+4) |
文件 | 分区 | offset范围 | 数据 |
2.txt | 1 | (0, 0+4) | 1 234 |
2 | (4, 4+4) |