关于scala:Spark textFile vs WholeTextFiles

Spark textFile vs wholeTextFiles

我了解textFile为每个文件生成分区的基本原理,而wholeTextFiles生成对值的RDD,其中键是每个文件的路径,值是每个文件的内容。

现在,从技术angular来看,两者之间有什么区别:

1
2
val textFile = sc.textFile("my/path/*.csv", 8)
textFile.getNumPartitions

1
2
val textFile = sc.wholeTextFiles("my/path/*.csv",8)
textFile.getNumPartitions

在这两种方法中,我都会生成8个分区。那么,为什么我应该首先使用wholeTextFiles呢?与textFile相比,它有什么好处?


正如您提到的,

主要区别在于textFile将以每行作为元素返回一个RDD,而wholeTextFiles将以密钥为文件路径的PairRDD返回。如果不需要根据文件来分离数据,只需使用textFile

使用textFile读取未压缩的文件时,会将数据拆分为32MB的块。从内存的angular来看,这是有利的。这也意味着将丢失行的顺序,如果应保留顺序,则应使用wholeTextFiles

wholeTextFiles将立即读取文件的完整内容,不会部分溢出到磁盘或部分垃圾回收。每个文件将由一个内核处理,并且每个文件的数据将是一台计算机,因此很难分配负载。


textFile generating partition for each file, while wholeTextFiles generates an RDD of pair values

那是不准确的:

  • textFile加载一个或多个文件,每行作为结果RDD中的一条记录。如果文件足够大(取决于请求的分区数,Spark \\的默认分区数和基础的文件系统),则单个文件可能会分成几个分区。一次加载多个文件时,此操作会"丢失"记录和包含该记录的文件之间的关系-也就是说,无法知道哪个文件包含哪一行。 RDD中的记录顺序将遵循文件的字母顺序,以及文件内的记录顺序(该顺序不是" lost ")。

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

  • 通常来说,textFile用于仅加载大量数据的通用用例(无论如何将其分解为文件)。仅当您确实需要知道每个记录的原始文件名并且知道所有文件都足够小时,才应使用readWholeFiles


    自Spark2.1.1起,以下是textFile的代码。

    1
    2
    3
    4
    5
    6
    7
    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的语法如下

    1
    2
    3
    def wholeTextFiles(
      path: String,
      minPartitions: Int = defaultMinPartitions): RDD[(String, String)] = withScope

    如果我们观察到两种方法的语法相同,但是textfile可用于读取文件,其中,WholeTextFiles用于读取小文件的目录。我们怎么也可以使用更大的文件,但是性能可能会有所影响。
    因此,当您要处理大文件时,textFile是更好的选择,而如果要处理小文件的目录,则WholeTextFile是更好的选择


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

  • wholeTextFile()读取文本文件的目录并返回pairRDD。
    例如,如果目录中的文件很少,那么WholeTextFile()方法将创建RDD对,其中文件名和路径为键,值是整个文件为字符串。


  • 为清楚起见,请参见以下示例:-

    1
    2
    textFile = sc.textFile("ml-100k/u1.data")
    textFile.getNumPartitions()

    输出-2
    即2个分区

    1
    2
    textFile = sc.wholeTextFiles("ml-100k/u1.data")
    textFile.getNumPartitions()

    输出-1
    即只有一个分区。

    所以总的来说,WholeTextFiles

    从HDFS,本地文件系统(在所有节点上都可用)或任何Hadoop支持的文件系统URI中读取文本文件目录。每个文件都作为单个记录读取,并以键值对的形式返回,其中键是每个文件的路径,值是每个文件的内容。