一文看懂Spark中reduceByKey 和 groupByKey 的区别

2023-11-13

目录

一、先看结论

二、举例、画图说明

1.实现的功能分别是什么?

1).groupByKey 实现 WordCount

2).reduceByKey 实现 WordCount

2.画图解析两种实现方式的区别

1) groupByKey 实现 WordCount

2).reduceByKey 实现 WordCount(简单流程)

3).reduceByKey 实现 WordCount(终极流程)


一、先看结论

1.从Shuffle的角度

reduceByKey 和 groupByKey都存在shuffle操作,但是reduceByKey可以在shuffle之前对分区内相同key的数据集进行预聚合(combine),这样会减少落盘的数据量,而groupByKey只是进行分组,不存在数据量减少的问题,reduceByKey性能比较高。

2.从功能的角度

 reduceByKey其实包含分组和聚合的功能;groupByKey只能分组,不能聚合,所以在分组聚合的场合下,推荐使用reduceByKey,如果仅仅是分组而不需要聚合,那么还是只能使用groupByKey。

        

二、举例、画图说明

1.实现的功能分别是什么?

为方便理解,分别用两个算子来实现WordCount程序。假设单词已经被处理成(word,1)的形式,我用List(("a", 1), ("a", 1), ("a", 1), ("b", 1))作为数据源。

1).groupByKey 实现 WordCount

  功能:groupByKey可以将数据源的数据根据 key 对 value 进行分组

  首先来看下,单单使用groupByKey,其返回值是什么

  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(sparkConf)
    // 获取 RDD
    val rdd = sc.makeRDD(List(("a", 1), ("a", 1), ("a", 1), ("b", 1)))
    val reduceRDD = rdd.groupByKey()
    reduceRDD.collect().foreach(println)
    sc.stop()
    /**
     * 运行结果:
     * (a,CompactBuffer(1, 1, 1))
     * (b,CompactBuffer(1))
     */
  }

可以看到,返回的结果是RDD[(String, Iterable[Int])],也就是(a,(1,1,1)),(b,(1,1,1))。

若要实现WordCount,还需要一步Map操作:

  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(sparkConf)
    // 获取 RDD
    val rdd = sc.makeRDD(List(("a", 1), ("a", 1), ("a", 1), ("b", 1)))
    val reduceRDD = rdd.groupByKey().map {
      case (word, iter) => {
        (word, iter.size)
      }
    }
    reduceRDD.collect().foreach(println)
    sc.stop()

    /**
     * 运行结果:
     * (a,3)
     * (b,1)
     */
  }

2).reduceByKey 实现 WordCount

功能:reduceByKey可以将数据按照相同的 Key 对 Value 进行两两聚合,这个聚合的方式是需要指定的。

  def main(args: Array[String]): Unit = {
    val sparkConf = new SparkConf().setMaster("local[*]").setAppName("Operator")
    val sc = new SparkContext(sparkConf)
    // 获取 RDD
    val rdd = sc.makeRDD(List(("a", 1), ("a", 1), ("a", 1), ("b", 1)))
    // 指定计算公式为 x+y
    val reduceRDD = rdd.reduceByKey((x,y) => x + y)
    reduceRDD.collect().foreach(println)
    sc.stop()
    /**
     * 运行结果:
     * (a,3)
     * (b,1)
     */
  }

2.画图解析两种实现方式的区别

为方便演示Shuffle过程,现在假设有两个分区的数据。

1) groupByKey 实现 WordCount

解读:

1.红色RDD是数据源,包含两个分区的(word,1)数据

2.Shuffle过程(都知道Shuffle过程是需要磁盘IO的)

3.groupByKey后的RDD,根据key分组对Value进行聚合

4.Map操作计算WordCount

总结:groupbykey 会导致数据打乱重组,存在shuffle操作。

2).reduceByKey 实现 WordCount(简单流程)

解读:

1.红色RDD是数据源,包含两个分区的(word,1)数据

2.Shuffle过程

3.根据指定的聚合公式,对Value进行两两聚合后的结果RDD

到这来看,感觉 groupbykey 和 reduceByKey 实现WordCount的计算方式来看感觉差不多嘛,从性能上来说,都有Shuffle操作,所以从计算性能上来说没多大区别;从功能上来说,都有分组,只是reduceByKey有聚合操作,而groupbykey没有聚合操作,它的聚合是通过增加map操作来实现的,所以看似也没多大区别。

那么究竟他两的核心区别是什么呢?

3).reduceByKey 实现 WordCount(终极流程)

再来一遍reduceByKey的功能介绍:可以将数据按照相同的 Key 对 Value 进行两两聚合。

思考一个问题:从 2) 的图中有没有发现一个现象,在红色RDD的一个分区中就有相同的Key,而且value是可以聚合的。在 groupbykey 实现过程中,由于groupbykey没有聚合功能,实现聚合计算是将所有数据分组完成后再进行聚合。而 reduceByKey 是有聚合功能的,实现过程中,在分组前也同样满足聚合条件(有相同的key,value能聚合),那么reduceByKey是不是在分组前就将数据先进行聚合了呢?(答案是肯定的,我们叫预聚合操作)

所以,它的流程图就变成这样:

解读:

1.红色RDD是数据源,包含两个分区的(word,1)数据,在分组前先对分区内的数据进行预聚合

2.Shuffle操作

3.根据指定的聚合公式,对Value进行两两聚合后的结果RDD

有哪些变化呢?

1.分组前对数据进行了预聚合,参与分组的数据量变小,也即参与Shuffle的数据量变小

2.因为参与Shuffle的数据量变小,所以Shuffle时的磁盘IO次数将变少

3.聚合计算时量量计算的次数变少

由此可以得出一个结论

        reduceByKey支持分区内预聚合功能,可以有效减少Shuffle时落盘的数据量,提升Shuffle的性能。  

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一文看懂Spark中reduceByKey 和 groupByKey 的区别 的相关文章

  • mysql底层数据存储原理

    一 前言 1 1 数据存储在哪里 操作系统从寄存器中读取数据是最快的 因为它离CPU最近 但是寄存器有个非常致命的问题是 它只能存储非常少量的数据 设计它的目的主要是用来暂存指令和地址 并非存储大量用户数据的 内存的大小虽然比寄存器大 但是
  • Java 封装、继承、多态的理解

    更好的阅读体验 Java 封装 继承 多态的理解 1 封装 封装 就是隐藏对象的属性和实现细节 仅对外提供公共访问方式 让使用者知道的才暴露出来 不需要让使用者知道的全部隐藏起来 封装的好处 避免使用者直接操作属性值 隐藏类的实现细节 让使
  • python函数可变参数问题

    函数参数 必选参数 默认参数 可选参数 关键字参数 1 有默认参数和可变参数 argment def test a b 0 c print a b c test 1 2 运行结果 1 2 由此可以看出参数是按顺序传递的 不管参数是不是有默认

随机推荐

  • wiredtiger java_Mongodb WT_ERROR:非特定的WiredTiger错误,

    我试过这个命令 mongod repair dbpath storageEngine wiredTiger并收到同样的错误 Mongo版本v3 4 9 当我尝试启动指向现在损坏的数据库的mongo时出现错误 E STORAGE initan
  • 科技云报道:5G还未普及,6G已经来了?

    科技云报道原创 2021年 相信大部分人仍在用着4G网络 甚至都没明白什么是5G 就开始听到6G的消息了 近日 国家知识产权局知识产权发展研究中心发布了 6G通信技术专利发展状况报告 对6G关键技术的专利发展情况进行深度解读 报告显示 当前
  • mysql状态下,命令行清空指令

    mysql状态下 命令行清空指令
  • attention机制_【CV中的Attention机制】SelectiveKernelNetworksSE进化版

    前言 SKNet是SENet的加强版 是attention机制中的与SE同等地位的一个模块 可以方便地添加到现有的网络模型中 对分类问题 分割问题有一定的提升 作者 pprp 编辑 BBuf 1 SKNet SKNet是SENet的加强版
  • QT中QLoggingCategory类的作用

    使用前须知 include category 美 k t ri 种类 类别 使用举例 QLoggingCategory setFilterRules QStringLiteral qt modbus true 作用总结 控制打印输出类别和区
  • html5 first child,childfirst

    在html里 firstchild 有什么作用 表示对第一个字对象的引用 如 DIV的子对象 alert document getElementById abc firstChild tagname 返回SPAN alert documen
  • vcruntime140_1.dll丢失的详细解决办法

    今天准备打开CAD跟ps时候 当打开我自己的ps软件后 弹出了一个对话框 内容是 由于找不到vcruntime140 1 dll 无法继续执行代码 重新安装程序可能会解决此问题 我很纳闷 前几天还好好着呢 于是我上网上查了一下 成功解决了问
  • signature=0e936ad5c99bd8d603e71fa74e787bee,JavaScript 的 BASE64 算法 实现 完美解决中文乱码...

    收藏的Base64编码 解码 在一个外国网站看到的 不过对中文不支持 自己加入了escape 对中文也支持了 先用escape 对中文进行编码 然后再进行base64编码 解码时 再加入 对中文进行解码 p gt W3C DTD HTML
  • URL 链接中 #、?、连接符& 分别有什么作用?

    在一个 URL 中可以包含很多的内容 其中不仅仅是包含 26 个英文字母 10 个罗马数字 中文汉字 还可以拥有井号 问号 连接符 等三种最常见的符号 那么这些符号在网站中都有哪些作用呢 文章目录 一 井号 二 问号 三 连接 一 井号 井
  • Qt:十六进制字符串和十六进制互转

    Qt 十六进制字符串和十六进制互转 前言 一 字符串转换十六进制 1 封装函数 2 函数调用示例 二 16进制转换字符串 前言 网上查了不少方式 踩了不少坑 最终这个方式是我目前使用感觉较好的一种 具体出处已经没印象了 这里放出完整代码供大
  • Spring(二)IOC容器的初始化流程

    文章目录 一 Spring 核心容器类 1 1 BeanFactory 1 2 ApplicationContext 1 3 BeanDefinition 二 IOC容器的初始化 2 1 基于Xml的IOC容器的初始化 2 1 1 寻找入口
  • 15个顶级Java多线程面试题及答案

    1 现在有T1 T2 T3三个线程 你怎样保证T2在T1执行完后执行 T3在T2执行完后执行 这个线程问题通常会在第一轮或电话面试阶段被问到 目的是检测你对 join 方法是否熟悉 这个多线程问题比较简单 可以用join方法实现 2 在Ja
  • LLM在放射科学中应用潜力

    本论文在全球范围内评估了 31 个大型语言模型 LLM 在解读放射科报告并从放射学发现中推导出诊断信息 impression 任务上的表现 这是目前已知的对全球 LLM 用于放射科学自然语言处理 NLP 进行的最全面评估之一 该研究通过在这
  • 8款常见的自动化测试开源框架

    在如今开源的时代 我们就不要再闭门造车了 热烈的拥抱开源吧 本文针对性能测试 Web UI 测试 API 测试 数据库测试 接口测试 单元测试等方面 为大家整理了github或码云上优秀的自动化测试开源项目 希望能给大家带来一点帮助 一 性
  • 运维体系的构建

    文章目录 一 前言 二 基础 2 1 项目摸底 2 2 做一个好辅助 2 3 学习业务 2 4 标准与流程 2 5 维护 三 进阶 3 1 系统 服务优化 3 2 工作流程优化 3 3 规矩 3 4 运维管理平台 一 前言 运维的基础工作通
  • php lazy loading,React丨用户体验丨hook版 lazy loading

    我们都知道随着单页应用 bundle 的体积不断增大 会造成首次加载时间过长 白屏时间过长 过程中会加载了我们首页没有必要看到的一些 页面 组件 js文件 所以我们需要对 bundle 文件进行拆分来进行按需加载 懒加载 这里需要用到 we
  • Xilinx FIFO Generator 需要注意RST复位

    Xilinx FIFO Generator 需要注意RST复位 系列文章推荐 Xilinx FIFO Generator 需要注意RST复位 Xilinx FIFO Generator 需要注意Actual Depth Xilinx FIF
  • cvCloneImage()内存泄漏解决方法, cvCloneImage()和cvCopy()的区别

    转自 http blog csdn net stellar0 article details 8741759 cvCloneImage 每次使用时编译器会分配新的内存空间 不会覆盖以前的内容 所以如果在循环中使用内存会迅速减小 每次用完都需
  • Python 计算机视觉(六)—— OpenCV 进行图像量化与采样

    对于信号的采样可以参考我之前的文章 数字信号处理 2 1 采样 对于信号的量化可以参考 数字信号处理 2 4 ADC 中的有限字长效应 在本篇文章中绘图使用到了 matplotlib 库 需要了解学习可以参考我之前写的用来总结这个绘图库的文
  • 一文看懂Spark中reduceByKey 和 groupByKey 的区别

    目录 一 先看结论 二 举例 画图说明 1 实现的功能分别是什么 1 groupByKey 实现 WordCount 2 reduceByKey 实现 WordCount 2 画图解析两种实现方式的区别 1 groupByKey 实现 Wo