在使用Spark SQL的过程中,经常会用到groupBy这个函数进行一些统计工作。但是会发现除了groupBy外,还有一个groupByKey(注意RDD也有一个groupByKey,而这里的groupByKey是DataFrame的)。这个groupByKey引起了我的好奇,那我们就到源码里面一探究竟吧。

所用spark版本:spark2.1.0

先从使用的角度来说,

groupBy:groupBy类似于传统SQL语言中的group by子语句,但比较不同的是groupBy()可以带多个列名,对多个列进行group。比如想根据"id"和"name"进行groupBy的话可以

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

groupBy返回的类型是RelationalGroupedDataset。

groupByKey:groupByKey则更加灵活,可以根据用户自己对列的组合来进行groupBy,比如上面的那个例子,根据"id"和"name"进行groupBy,使用groupByKey可以这样。

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

但和groupBy不同的是groupByKey返回的类型是KeyValueGroupedDataset。

下面来看看这两个方法的实现有何区别。

groupBy源码

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

最终会去新建一个RelationalGroupedDataset,而这个方法提供count(),max(),agg(),等方法。值得一提的是,这个类在spark1.x的时候类名为“GroupedData”。看看类中的注释吧

/**
* 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。

我们再看看这个类中的注释吧

/**
* :: 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。

总而言之,groupByKey虽然提供了更加灵活的处理grouping的方式,但groupByKey后返回的类是KeyValueGroupedDataset,它里面所提供的操作接口也不如groupBy返回的RelationalGroupedDataset所提供的接口丰富。除非真的有一些特殊的grouping操作,否则还是使用groupBy吧。

Spark DataFrame的groupBy vs groupByKey的更多相关文章

  1. spark dataframe操作集锦(提取前几行,合并,入库等)

    https://blog.csdn.net/sparkexpert/article/details/51042970 spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当 ...

  2. spark DataFrame 常见操作

    spark dataframe派生于RDD类,但是提供了非常强大的数据操作功能.当然主要对类SQL的支持. 在实际工作中会遇到这样的情况,主要是会进行两个数据集的筛选.合并,重新入库. 首先加载数据集 ...

  3. spark dataframe unionall

    今天本来想写一个spark dataframe unionall的demo,由于粗心报下面错误: Exception in thread "main" org.apache.spa ...

  4. 在Spark中尽量少使用GroupByKey函数(转)

    原文链接:在Spark中尽量少使用GroupByKey函数 为什么建议尽量在Spark中少用GroupByKey,让我们看一下使用两种不同的方式去计算单词的个数,第一种方式使用reduceByKey  ...

  5. pandas.DataFrame的groupby()方法的基本使用

    pandas.DataFrame的groupby()方法是一个特别常用和有用的方法.让我们快速掌握groupby()方法的基础使用,从此数据分析又多一法宝. 首先导入package: import p ...

  6. Spark DataFrame中的join使用说明

    spark sql 中join的类型 Spark DataFrame中join与SQL很像,都有inner join, left join, right join, full join; 类型 说明 ...

  7. 转】Spark DataFrame小试牛刀

    原博文出自于: https://segmentfault.com/a/1190000002614456 感谢! 三月中旬,Spark发布了最新的1.3.0版本,其中最重要的变化,便是DataFrame ...

  8. spark DataFrame的创建几种方式和存储

    一. 从Spark2.0以上版本开始,Spark使用全新的SparkSession接口替代Spark1.6中的SQLContext及HiveContext接口来实现其对数据加载.转换.处理等功能.Sp ...

  9. spark dataframe 类型转换

    读一张表,对其进行二值化特征转换.可以二值化要求输入类型必须double类型,类型怎么转换呢? 直接利用spark column 就可以进行转换: DataFrame dataset = hive.s ...

随机推荐

  1. 征服诱人的Vagrant!

    一.背景 ​ 最近要开始深入学习分布式相关的东西了,那第一步就是在自己的电脑上安装虚拟机,以前在Windows平台,我选择用VMware Workstation作为虚拟机软件,现在在Mac系统下,感觉 ...

  2. SpringBoot 常用注解

    @SpringBootApplication  这个配置等同于:@Configuration ,@EnableAutoConfiguration 和 @ComponentScan 三个配置. @Ena ...

  3. for循环中let与var的区别,块级作用域如何产生与迭代中变量i如何记忆上一步的猜想

    我在前一篇讨论let与var区别的博客中,顺带一笔带过了let与var在for循环中的不同表现,虽然解释了是块级作用域的影响,但具体是怎么去影响的呢,我尝试的去理解了下,这篇博客主要从for循环步骤拆 ...

  4. python的Web框架,Django自定义过滤器及标签

    代码布局 有的时候框架给的过滤器不够用,需要自定义一些过滤器,所以就需要我们自己来定义一些过滤器等 自定义代码放置的路径 某个app特用(独有)的 - app 目录下的 templatetags文件夹 ...

  5. NPOI导出EXCEL报_服务器无法在发送 HTTP 标头之后追加标头

    虽然发表了2篇关于NPOI导出EXCEL的文章,但是最近再次使用的时候,把以前的代码粘贴过来,居然报了一个错误: “服务器无法在发送 HTTP 标头之后追加标头” 后来也查询了很多其他同学的文章,都没 ...

  6. [转]js 取得 Unix时间戳(Unix timestamp)

    本文转自:https://blog.csdn.net/o0snow/article/details/6858829 js 取得 Unix时间戳 Unix时间戳(Unix timestamp),或称Un ...

  7. JPA、Hibernate、Spring data jpa之间的关系,终于明白了

    什么么是JPA? 全称Java Persistence API,可以通过注解或者XML描述[对象-关系表]之间的映射关系,并将实体对象持久化到数据库中. 为我们提供了: 1)ORM映射元数据:JPA支 ...

  8. 软件测试工程师这样面试,拿到offer的几率是80%

    面试难还是不难?取决于面试者的底蕴(气场+技能).心态和认知及沟通技巧.面试其实可以理解为一场聊天和谈判,在这过程中有心理.思想上的碰撞和博弈.其实你只需要搞清楚一个逻辑:“面试官为什么会这样问?他希 ...

  9. 构建SpringBoot第一个Demo

    使用官方地址生成项目 https://start.spring.io  Generate:可以选择Maven或者Gradle构建项目 语言:我想一般都是Java 接下来选择SpringBoot的版本, ...

  10. HTML设为首页/加入收藏代码

    (特别注意:要把'这个符号换成无任何输入法状态中输入的'这个符号,否则程序无法运行)   1.文字型:     <a onclick="this.style.behavior='url ...