从S3读取CSV文件到Spark数据帧是否会如此之慢?

Tim*_*yan 11 amazon-s3 apache-spark

我正在构建一个需要从S3加载数据集的应用程序.功能正常,但性能出乎意料地慢.

数据集采用CSV格式.每个文件中大约有7M条记录(行),每个文件大小为600-700MB.

val spark = SparkSession
       .builder()
       .appName("MyApp")
       .getOrCreate()

val df = spark
     .read
    .option("header", "true") 
    .option("inferSchema", "true") 
    .csv(inFileName:_*)
    // inFileName is a list that current contains 2 file names
    // eg.  s3://mybucket/myfile1.csv

val r = df.rdd.flatMap{ row =>
      /*
       * Discard poorly formated input records 
       */
      try {
        totalRecords.add(1)

        // this extracts several columns from the dataset
        // each tuple of indexColProc specifies the index of the column to
        // select from the input row, and a function to convert
        // the value to an Int
        val coords = indexColProc.map{ case (idx, func) => func( row.get(idx).toString ) }

        List( (coords(0), coords) )
      }
      catch {
        case e: Exception => {    
          badRecords.add(1)
          List()
        }
      }
    }

println("Done, row count " + r.count )
Run Code Online (Sandbox Code Playgroud)

我在一台包含5台机器的AWS集群上运行它,每台机器都是m3.xlarge.maximizeResourceAllocation参数设置为true,这是群集上运行的唯一应用程序.

我运行了两次应用程序.第一次使用'inFileName'指向S3上的文件,第二次指向hadoop文件系统中文件的本地副本.

当我查看Spark历史记录服务器并深入查看与最终r.count操作相对应的作业时,我发现在访问s3上的文件时需要2.5分钟,而在hdfs上本地访问文件需要18秒.当我在较小的集群或master =本地配置上运行相同的实验时,我得到了相似的结果.

当我使用s3将s3文件复制到集群时

aws s3 cp <file>
Run Code Online (Sandbox Code Playgroud)

移动一个600-700MB文件只需6.5秒.因此,似乎机器实例的原始I/O对减速的贡献不大.

当访问s3时,这种性能是否会降低?如果没有,有人可以指出我出错的地方.如果是预期的话,还有其他方法可以做到更好的表现吗?或者我是否需要开发一些东西,只需在应用程序运行之前将文件从s3复制到hdfs?

Tim*_*yan 11

经过一番挖掘后,我发现使用S3原生产生了巨大的变化.我刚刚将URI前缀更改为s3n://,并且相关作业的性能从2.5分钟下降到21秒.因此,访问s3 vs hdfs只需要3s的惩罚,这是非常合理的.

在搜索此主题时,有很多帖子提到s3n的最大文件大小限制为5GB.但是,我发现说明Hadoop 2.4.0中的最大文件大小限制增加到5TB.

"不再推荐使用S3块文件系统."