为什么Spark将分区设置为文件大小(以字节为单位)?

时间:2017-11-15 22:16:56

标签: hadoop apache-spark

我有一个非常简单的pyspark程序,应该从S3读取CSV文件:

r = sc.textFile('s3a://some-bucket/some-file.csv')
  .map(etc... you know the drill...)

运行本地Spark节点时失败(它在EMR中工作)。我收到了OOM错误和GC崩溃。经过进一步检查,我意识到分区数量非常高。在此特定情况下,r.getNumPartitions()将返回2358041

我意识到这完全是我文件的大小(以字节为单位)。当然,这会让Spark崩溃。

我尝试过不同的配置,例如chaning mapred.min.split.size

conf = SparkConf()
conf.setAppName('iRank {}'.format(datetime.now()))
conf.set("mapred.min.split.size", "536870912")
conf.set("mapred.max.split.size", "536870912")
conf.set("mapreduce.input.fileinputformat.split.minsize", "536870912")

我还尝试使用repartition或将分区参数更改为textFile,但无济于事。

我很想知道是什么让Spark认为从文件大小中获取分区数量是一个好主意。

2 个答案:

答案 0 :(得分:2)

一般来说,它没有。正如This is the resulting image eliasah中的his answer很好地解释了minPartitions使用hadoopConfiguration JavaSparkContext(如果没有提供,则为2)和Hadoop输入格式计算的拆分。

后者只会在配置指示的情况下过高。这表明某些配置文件会干扰您的程序。

您的代码可能存在的问题是您使用了错误的配置。应使用sc = ... # type: SparkContext sc._jsc.hadoopConfiguration().setInt("mapred.min.split.size", min_value) sc._jsc.hadoopConfiguration().setInt("mapred.max.split.size", max_value) 而不是Spark配置来设置Hadoop选项。看起来您使用Python,因此您必须使用私有{{1}}实例:

{{1}}

答案 1 :(得分:1)

Hadoop 2.6实际上有一个错误可以做到这一点;最初的S3A版本没有为Spark分割提供块大小,默认值“0”表示每个作业一个字节。

以后的版本都应该使用fs.s3a.block.size作为指定块大小的配置选项...类似33554432(= 32 MB)的东西将是一个开始。

如果您使用的是Hadoop 2.6.x.不要使用S3A。这是我的建议。