【问题标题】:Spark textFile vs wholeTextFilesSpark textFile 与 wholeTextFiles
【发布时间】:2018-04-18 04:52:33
【问题描述】:

我了解textFile为每个文件生成分区的基本原理,而wholeTextFiles生成一个pair values的RDD,其中key是每个文件的路径,value是每个文件的内容。

现在,从技术角度来看,有什么区别:

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

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

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

【问题讨论】:

    标签: scala apache-spark file-io


    【解决方案1】:

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

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

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

    【讨论】:

      【解决方案2】:

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

      这不准确:

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

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

      一般来说,textFile 服务于仅加载大量数据的常见用例(无论数据如何分解为文件)。 readWholeFiles 应该只在您确实需要知道每条记录的原始文件名时使用,并且如果您知道所有文件都足够小。

      【讨论】:

      • 这似乎是更准确的答案。
      • 排序方面与接受的答案不同。我同意这里。
      【解决方案3】:

      从 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 读取本地文件、HDFS 文件和 S3,使用 file://hdfs://s3a:// 等模式

      WholeTextFile 的语法如下

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

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

      【讨论】:

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

        2. wholeTextFile() 读取文本文件目录并返回 pairRDD。 例如,如果目录中的文件很少,wholeTextFile() 方法会创建pair RDD,其中文件名和路径为key,value 为整个文件为字符串。

        【讨论】:

          【解决方案5】:

          为了清楚起见,请参见下面的示例:-

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2023-04-03
            • 1970-01-01
            • 2017-08-29
            • 2017-07-27
            • 2015-06-21
            相关资源
            最近更新 更多