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