如何在Spark中进行groupby后运行RDD操作?

时间:2016-05-09 20:33:42

标签: apache-spark pyspark bigdata

我想要执行群集的大量数据。问题是,我不希望整个集合有一个集群,但每个用户都需要集群。基本上我会先用userid做一个groupby,然后运行KMeans。

问题是,一旦你执行了groupby,任何映射都将在spark控制器上下文之外,因此任何创建RDD的尝试都将失败。 mllib中Spark的KMeans lib需要一个RDD(因此它可以并行化)。

我看到两个解决方法,但我希望有更好的解决方案。

1)手动循环控制器中的所有成千上万的用户(当事情变大时可能有数百万用户),并为每个用户运行kmeans。

2)在控制器中执行groupby,然后在map中运行由外部库提供的非并行kmeans。

请告诉我还有另一种方式,我宁愿拥有一切||尽可能。

1 个答案:

答案 0 :(得分:1)

编辑:我在回复时并不知道它是pyspark。但是,我会将其留作可以改编的想法

我有类似的问题,我能够提高性能,但它仍然不是我理想的解决方案。也许对你来说它可以奏效。

我们的想法是在许多较小的RDD(每个用户ID为一个新的RDD)中打破RDD,将它们保存到数组中,然后为每个" sub-RDD&调用处理函数(在您的情况下为聚类) #34 ;.建议的代码如下(注释中的解释):

// A case class just to use as example
case class MyClass(userId: Long, value: Long, ...)

// A Scala local array with the user IDs (Could be another iterator, such as List or Array):
val userList: Seq[Long] = rdd.map{ _.userId }.distinct.collect.toSeq  // Just a suggestion!

// Now we can create the new rdds:
val rddsList: Seq[RDD[MyClass]] = userList.map { 
  userId => rdd.filter({ item: MyClass => item.userId == userId }) 
}.toSeq

// Finally, we call the function we want for each RDD, saving the results in a new list. 
// Note the ".par" call, which is used to start the expensive execution for multiple RDDs at the same time
val results = rddsList.par.map {
  r => myFunction(r)
}

我知道这与您的第一个选项大致相同,但通过使用.par调用,我能够提高性能。

此调用将rddsList对象转换为https://us.mc-api.net/对象。这个新的Scala对象允许并行计算,因此理想情况下,map函数会同时为多个RDD调用myFunction(r),这可以提高性能。

有关并行收藏的详细信息,请查看ParSeq