在使用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
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](
@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吧。