使用Spark SQL GROUP BY对DataFrame进行高效的PairRDD操作

时间:2015-08-03 06:27:44

标签: scala apache-spark apache-spark-sql rdd

这个问题是关于聚合操作DataFrameRDD之间的二元性。在Spark SQL中,可以使用表生成UDF进行自定义聚合,但创建其中一个UDF通常明显不如使用RDD可用的聚合函数,特别是如果不需要表输出。

是否有一种有效的方法将{RDD}操作(例如aggregateByKey)应用于已使用GROUP BY分组或使用ORDERED BY进行排序的DataFrame?

通常,需要一个明确的map步骤来创建键值元组,例如dataFrame.rdd.map(row => (row.getString(row.fieldIndex("category")), row).aggregateByKey(...)。这可以避免吗?

1 个答案:

答案 0 :(得分:1)

不是真的。虽然DataFrames可以转换为RDDs,反之亦然,但这是相对复杂的操作,DataFrame.groupBy之类的方法与RDD上的对应方法具有相同的语义。

你可以得到的最接近的东西是Spark 1.6.0中引入的a new DataSet API。它提供了与DataFramesGroupedDataset类更紧密的集成,并使用自己的一套方法,包括reducecogroupmapGroups

case class Record(id: Long, key: String, value: Double)

val df = sc.parallelize(Seq(
    (1L, "foo", 3.0), (2L, "bar", 5.6),
    (3L, "foo", -1.0), (4L, "bar", 10.0)
)).toDF("id", "key", "value")

val ds = df.as[Record]
ds.groupBy($"key").reduce((x, y) => if (x.id < y.id) x else y).show

// +-----+-----------+
// |   _1|         _2|
// +-----+-----------+
// |[bar]|[2,bar,5.6]|
// |[foo]|[1,foo,3.0]|
// +-----+-----------+

在某些特定情况下,可以使用Orderable语义来使用structsarrays对数据进行分组和处理。您将在SPARK DataFrame: select the first row of each group

中找到一个示例