我有一个文本文件,由大量由空格分隔的随机浮动值组成。 我正在将此文件加载到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获得解决方案,以及如何在流程函数中访问该索引?地图会对分区进行洗牌。
答案 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?
中所经历的那样