Spark DataFrame的groupBy vs groupByKey

在使用Spark SQL的過程當中,常常會用到groupBy這個函數進行一些統計工做。可是會發現除了groupBy外,還有一個groupByKey(注意RDD也有一個groupByKey,而這裏的groupByKey是DataFrame的)。這個groupByKey引發了個人好奇,那咱們就到源碼裏面一探究竟吧。sql

所用spark版本:spark2.1.0session

先從使用的角度來講,
groupBy:groupBy相似於傳統SQL語言中的group by子語句,但比較不一樣的是groupBy()能夠帶多個列名,對多個列進行group。好比想根據"id"和"name"進行groupBy的話能夠函數

df.goupBy("id","name")

groupBy返回的類型是RelationalGroupedDataset。spa

groupByKey:groupByKey則更加靈活,能夠根據用戶本身對列的組合來進行groupBy,好比上面的那個例子,根據"id"和"name"進行groupBy,使用groupByKey能夠這樣。code

//同前面的goupBy效果是同樣的,但返回的類型是不同的
df..toDF("id","name").goupByKey(row =>{
    row.getString(0) + row.getString(1)
})

但和groupBy不一樣的是groupByKey返回的類型是KeyValueGroupedDataset。接口

下面來看看這兩個方法的實現有何區別。ip

groupBy源碼

def groupBy(cols: Column*): RelationalGroupedDataset = {
    RelationalGroupedDataset(toDF(), cols.map(_.expr), RelationalGroupedDataset.GroupByType)
  }

最終會去新建一個RelationalGroupedDataset,而這個方法提供count(),max(),agg(),等方法。值得一提的是,這個類在spark1.x的時候類名爲「GroupedData」。看看類中的註釋吧ci

/**
 * A set of methods for aggregations on a `DataFrame`, created by `Dataset.groupBy`.
 *
 * The main method is the agg function, which has multiple variants. This class also contains
 * convenience some first order statistics such as mean, sum for convenience.
 *
 * This class was named `GroupedData` in Spark 1.x.
 *
 * @since 2.0.0
 */
@InterfaceStability.Stable
class RelationalGroupedDataset protected[sql](

groupByKey源碼

@Experimental
  @InterfaceStability.Evolving
  def groupByKey[K: Encoder](func: T => K): KeyValueGroupedDataset[K, T] = {
    val inputPlan = logicalPlan
    val withGroupingKey = AppendColumns(func, inputPlan)
    val executed = sparkSession.sessionState.executePlan(withGroupingKey)

    new KeyValueGroupedDataset(
      encoderFor[K],
      encoderFor[T],
      executed,
      inputPlan.output,
      withGroupingKey.newColumns)
  }

能夠發現最後生成和返回的類是KeyValueGroupedDataset。這是dataset的子類,表示聚合過以後的dataset。
咱們再看看這個類中的註釋吧get

/**
 * :: Experimental ::
 * A [[Dataset]] has been logically grouped by a user specified grouping key.  Users should not
 * construct a [[KeyValueGroupedDataset]] directly, but should instead call `groupByKey` on
 * an existing [[Dataset]].
 *
 * @since 2.0.0
 */
@Experimental
@InterfaceStability.Evolving
class KeyValueGroupedDataset[K, V] private[sql](

能夠發現groupByKey還處於實驗階段。它是但願能夠由用戶本身來實現groupBy的規則,而不像groupBy()同樣,須要被列屬性所束縛。
經過groupByKey用戶能夠按照本身的需求來進行grouping。input

總而言之,groupByKey雖然提供了更加靈活的處理grouping的方式,但groupByKey後返回的類是KeyValueGroupedDataset,它裏面所提供的操做接口也不如groupBy返回的RelationalGroupedDataset所提供的接口豐富。除非真的有一些特殊的grouping操做,不然仍是使用groupBy吧。

相關文章
相關標籤/搜索