Scala Spark:读取文本文件后的重新分区策略

Scala Spark:读取文本文件后的重新分区策略,scala,apache-spark,partition,Scala,Apache Spark,Partition,我通过以下方式启动了群集: /usr/lib/spark/bin/spark-submit --class MyClass --master yarn-cluster--num-executors 3 --driver-memory 10g --executor-memory 10g --executor-cores 4 /path/to/jar.jar 我要做的第一件事是读取一个大的文本文件,然后数一数: val file = sc.textFile("/path/to/file.txt.g

我通过以下方式启动了群集:

/usr/lib/spark/bin/spark-submit --class MyClass --master yarn-cluster--num-executors 3 --driver-memory 10g --executor-memory 10g --executor-cores 4 /path/to/jar.jar
我要做的第一件事是读取一个大的文本文件,然后数一数:

val file = sc.textFile("/path/to/file.txt.gz")
println(file.count())

执行此操作时,我看到只有一个节点实际读取文件并执行计数(因为我只看到一个任务)。这是预期的吗?我应该在以后重新分区我的RDD,还是在使用map reduce函数时,Spark会为我重新分区?

看起来您正在处理一个gzip文件

引述自:

我认为Gzip文件遇到了一个相当典型的问题,它们无法并行加载。更具体地说,一个gzip文件不能由多个任务并行加载,因此Spark将用一个任务加载它,从而为您提供一个带有一个分区的RDD

您需要在加载RDD后显式地重新划分它,以便更多的任务可以并行运行

例如:

val file = sc.textFile("/path/to/file.txt.gz").repartition(sc.defaultParallelism * 3)
println(file.count())
关于您问题的评论,此处设置
minPartitions
没有帮助的原因是,Spark将始终使用1个任务来读取文件


如果在读取常规文本文件或使用可拆分压缩格式(如bzip2)压缩的文件时设置
minPartitions
,您将看到Spark实际上会并行部署该数量的任务(直到集群中可用的内核数)来读取该文件。

您的“defaultMinPartitions”是什么?正如文档明确指出的,textFile采用了可选的分区数参数,默认值为。My defaultMinPartitions大于1。似乎我无法强制指定数量的分区,因为它只有一个文本文件。。。跑步val file=sc.textFile(“/path/to/file.txt.gz”,8)println(file.partitions.length)返回1好吧,它必须在一个地方读取,因为这本身就是串行的。但我不明白,如果它不做什么,为什么它会有那个可选参数。我明白了。。。所以,因为count做的不多,所以它只能由一个工人来完成。但是如果我运行map或reduce,它应该开始传播数据集?不知道,抱歉,但我猜应该。谢谢!那么你会推荐bzip2而不是gzip吗?如果我经常加载该文件,我应该采取什么策略来优化每次运行?@Stephane-这取决于传入的数据量以及集群花费多少时间重新划分数据。一个gzip文件就可以了。如果一个文件太大,您可能还可以使用多个gzip文件(即压缩前拆分),因为每个gzip文件可以并行加载到同一RDD中(每个文件一个任务)。这可能是阻力最小的路径。非常有趣,谢谢!所以.gz.001拆分了文件或bzip2。。。我两个都要试试!我认为是的,最大的瓶颈是第一次重新分区,因此如果我在文件到来时已经成功地拆分了文件,可能会节省一点时间time@Stephane,你知道为什么会存在这种限制吗?分发对非gzip文件的读取似乎并不容易——在这两种情况下,您都需要连续读取文件以确定下一条记录从何处开始?@Paul,我还没有尝试过bzip2,我会告诉您并行读取是否真的有效。我不知道,如果归档文件是可拆分的,那么我想你可以并行地读取它(块1到n,n+1到2n,等等),然后可能会到处发送丢失的几个字节,以确保每个部分都正确地形成。我希望Spark就是这么做的