Spark textFile vs wholeTextFiles

时间:2017-11-06 04:53:39

标签: scala apache-spark file-io

我理解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的好处是什么?

5 个答案:

答案 0 :(得分:14)

正如您所提到的,主要区别是textFile将返回RDD,每行作为元素,而wholeTextFiles返回PairRDD,其中键是文件路径。如果不需要根据文件分隔数据,只需使用textFile

使用textFile读取未压缩文件时,会将数据拆分为32MB的块。从记忆角度来看,这是有利的。这也意味着行的排序会丢失,如果要保留订单,则应使用wholeTextFiles

wholeTextFiles将立即读取文件的完整内容,不会部分溢出到磁盘或部分垃圾收集。每个文件将由一个核心处理,每个文件的数据将是一台机器,使得分配负载更加困难。

答案 1 :(得分:11)

  

textFile为每个文件生成分区,而wholeTextFiles生成对值的RDD

这不准确:

  1. textFile在生成的RDD中加载一个或多个文件,每个作为记录。如果文件足够大,则可以将单个文件拆分为多个分区(取决于请求的分区数,Spark的默认分区数以及基础文件系统)。当一次加载多个文件时,此操作“丢失”记录与包含它的文件之间的关系 - 即,无法知道哪个文件包含哪一行。 RDD中记录的顺序将遵循文件的字母顺序,以及文件中记录的顺序(顺序不会“丢失”)。

  2. wholeTextFiles通过将数据加载到PairRDD,每个输入文件一条记录,保留数据与包含它的文件之间的关系。记录的格式为(fileName, fileContent)。这意味着加载大型文件存在风险(可能会导致性能不佳或OutOfMemoryError,因为每个文件都必须存储在单个节点上)。分区是基于用户输入或Spark的配置完成的 - 多个文件可能被加载到单个分区中。

  3. 一般来说,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)

  1. textfile()读取文本文件并返回字符串的RDD。例如sc.textFile(“ / mydata.txt”)将创建RDD,其中每行都是一个元素。

  2. 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中读取文本文件目录。每个文件都作为一条记录读取,并以键值对的形式返回,其中键是每个文件的路径,值是每个文件的内容。