我理解textFile
为每个文件生成分区的基本理论,而wholeTextFiles
生成对值的RDD,其中键是每个文件的路径,值是每个文件的内容文件。
现在,从技术角度来看,有什么区别:
val textFile = sc.textFile("my/path/*.csv", 8)
textFile.getNumPartitions
和
val textFile = sc.wholeTextFiles("my/path/*.csv",8)
textFile.getNumPartitions
在这两种方法中,我都会生成8个分区。那么我为什么要首先使用wholeTextFiles
,它对textFile
的好处是什么?
答案 0 :(得分:14)
正如您所提到的,主要区别是textFile
将返回RDD,每行作为元素,而wholeTextFiles
返回PairRDD,其中键是文件路径。如果不需要根据文件分隔数据,只需使用textFile
。
使用textFile
读取未压缩文件时,会将数据拆分为32MB的块。从记忆角度来看,这是有利的。这也意味着行的排序会丢失,如果要保留订单,则应使用wholeTextFiles
。
wholeTextFiles
将立即读取文件的完整内容,不会部分溢出到磁盘或部分垃圾收集。每个文件将由一个核心处理,每个文件的数据将是一台机器,使得分配负载更加困难。
答案 1 :(得分:11)
textFile
为每个文件生成分区,而wholeTextFiles
生成对值的RDD
这不准确:
textFile
在生成的RDD中加载一个或多个文件,每个行作为记录。如果文件足够大,则可以将单个文件拆分为多个分区(取决于请求的分区数,Spark的默认分区数以及基础文件系统)。当一次加载多个文件时,此操作“丢失”记录与包含它的文件之间的关系 - 即,无法知道哪个文件包含哪一行。 RDD中记录的顺序将遵循文件的字母顺序,以及文件中记录的顺序(顺序不会“丢失”)。
wholeTextFiles
通过将数据加载到PairRDD
,每个输入文件一条记录,保留数据与包含它的文件之间的关系。记录的格式为(fileName, fileContent)
。这意味着加载大型文件存在风险(可能会导致性能不佳或OutOfMemoryError
,因为每个文件都必须存储在单个节点上)。分区是基于用户输入或Spark的配置完成的 - 多个文件可能被加载到单个分区中。
一般来说,textFile
提供了加载大量数据的常见用例(无论它是如何分解为文件的)。 readWholeFiles
只应在实际需要知道每条记录的原始文件名时使用{em>和,如果您知道所有文件都足够小的话。
答案 2 :(得分:1)
从Spark2.1.1开始,以下是textFile的代码。
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) }
内部使用hadoopFile以file://
,hdfs://
和s3a://
之类的模式读取本地文件,HDFS文件和S3
其中的WholeTextFile语法如下
def wholeTextFiles(
path: String,
minPartitions: Int = defaultMinPartitions): RDD[(String, String)] = withScope
如果我们观察到两种方法的语法都相同,但是 textfile 对于读取文件很有用,因为 wholeTextFiles 用于读取目录小文件。 但是我们也可以使用更大的文件,但是性能可能会有所影响。
因此,当您要处理大文件时,textFile是更好的选择,而如果我们要处理小文件的目录,则WholeTextFile是更好的选择
答案 3 :(得分:1)
textfile()读取文本文件并返回字符串的RDD。例如sc.textFile(“ / mydata.txt”)将创建RDD,其中每行都是一个元素。
wholeTextFile()读取文本文件的目录并返回pairRDD。 例如,如果目录中的文件很少,那么WholeTextFile()方法将创建RDD对,其中文件名和路径为键,值为整个文件为字符串。
答案 4 :(得分:0)
为清楚起见,请参见以下示例:-
textFile = sc.textFile("ml-100k/u1.data")
textFile.getNumPartitions()
输出-2
即2个分区
textFile = sc.wholeTextFiles("ml-100k/u1.data")
textFile.getNumPartitions()
输出-1
即只有一个分区。
所以简而言之 wholeTextFiles
从HDFS,本地文件系统(在所有节点上都可用)或任何Hadoop支持的文件系统URI中读取文本文件目录。每个文件都作为一条记录读取,并以键值对的形式返回,其中键是每个文件的路径,值是每个文件的内容。