如何分区RDD

时间:2014-07-10 08:28:32

标签: scala hadoop partitioning apache-spark rdd

我有一个文本文件,由大量由空格分隔的随机浮动值组成。 我正在将此文件加载到scala中的RDD中。 这个RDD如何分区?

此外,是否有任何方法可以生成自定义分区,以便所有分区具有相同数量的元素以及每个分区的索引?

val dRDD = sc.textFile("hdfs://master:54310/Data/input*")
keyval=dRDD.map(x =>process(x.trim().split(' ').map(_.toDouble),query_norm,m,r))

这里我从HDFS加载多个文本文件,进程是我正在调用的函数。 我可以使用mapPartitonsWithIndex获得解决方案,以及如何在流程函数中访问该索引?地图会对分区进行洗牌。

3 个答案:

答案 0 :(得分:1)

您可以使用合并功能生成自定义分区:

coalesce(numPartitions: Int, shuffle: Boolean = false): RDD[T]

答案 1 :(得分:1)

加载的rdd按默认分区程序分区:哈希码。要指定自定义分区程序,请使用可以检查自己的分区程序提供的rdd.partitionBy()。

我认为在这里使用coalesce()是可以的,因为通过api docs,coalesce()只能在我们减少分区数量时使用,甚至我们也不能使用coalesce()指定自定义分区程序。

答案 2 :(得分:1)

  

如何对RDD进行分区?

默认情况下,为每个HDFS分区创建一个分区,默认情况下为64MB。阅读更多here

  

如何跨分区平衡数据?

首先,看一下重新分区他的数据的三种方式:

1)传递第二个参数,即所需的最小分区数     对于你的RDD,进入textFile(),但要小心:

In [14]: lines = sc.textFile("data")

In [15]: lines.getNumPartitions()
Out[15]: 1000

In [16]: lines = sc.textFile("data", 500)

In [17]: lines.getNumPartitions()
Out[17]: 1434

In [18]: lines = sc.textFile("data", 5000)

In [19]: lines.getNumPartitions()
Out[19]: 5926

正如您所看到的,[16]没有达到预期的效果,因为RDD具有的分区数量已经大于我们请求的最小分区数。

2)使用repartition(),如下所示:

In [22]: lines = lines.repartition(10)

In [23]: lines.getNumPartitions()
Out[23]: 10

警告:这将调用随机播放,当你想要增加你的RDD所拥有的分区数时,应该使用它。

来自docs

  

随机播放是Spark的重新分发数据的机制,因此它可以跨分区进行不同的分组。这通常涉及跨执行程序和机器复制数据,使洗牌成为一项复杂而昂贵的操作。

3)使用coalesce(),如下所示:

In [25]: lines = lines.coalesce(2)

In [26]: lines.getNumPartitions()
Out[26]: 2

在这里,Spark知道你会缩小RDD并获得它的优势。详细了解repartition() vs coalesce()

但是,所有这些保证您的数据将在您的分区中完美平衡吗?不像我在How to balance my data across the partitions?

中所经历的那样