• join shuffle


    什么是宽窄依赖,及特殊join算子,join时何时产生shuffle,何时不产生shuffle

    1、 什么是宽窄依赖,
    宽依赖: 发生shuffle时,一定会产生宽依赖,宽依赖是一个RDD中的一个Partition被多个子Partition所依赖(一个父亲多有儿子),也就是说每一个父RDD的Partition中的数据,都可能传输一部分到下一个RDD的多个partition中,此时一定会发生shuffle

    窄依赖: 一个RDD中的一个 Partition最多 被一个 子 Partition所依赖(一个父亲有一个儿子)

    2、 Spark中产生宽窄依赖的依据是shuffle,当发生shuffle时,会产生宽依赖,基本上shuffle算子都会产生宽依赖,但是join除外,在执行join算子之前如果先执行groupByKey,执行groupByKey之后,会把相同的key分到同一个分区,再执行join算子,join算子是把key相同的进行join(只是对于k v形式的数据可以使用),不一定会产生shuffle ,有可能发生shuffle,也有可能不发生

    最后返回的结果是(Key,(rdd1的v,rdd2的v)),如下平行化创建,两个RDD,对其进行Join。这中情况下就不一定会产生shuffle,根据具体情况而言

    #第一种情况, 不使用groupByKey直接进行join
     val rdd1 = sc.parallelize(List("aa"->5,"bb"->5,"dd"->6,"aa"->3,"tt"->2))	   
     val rdd2 = sc.parallelize(List("bb"->1,"aa"->3,"dd"->3,"ss"->6))

    对于join,第一种情况,在join之前不是groupByKey,发生shuffle

    val rdd1 = sc.parallelize(List("aa"->5,"bb"->5,"dd"->6,"aa"->3"tt"->2),1)	   
    val rdd2 = sc.parallelize(List("bb"->1,"aa"->3,"dd"->3,"ss"->6),1)
    //设置两个rdd的分区都是1,相同,
    val joind: RDD[(String, (Int, Int))] = rdd1.join(rdd2)
    

    通过UI界面可以观察到,一共有三个stage,在join 时进行了shuffle
    在这里插入图片描述

    #第二种情况,分区相同,join之前进行groupByKey
     val rdd1 = sc.parallelize(List("aa"->5,"bb"->5,"dd"->6,"aa"->3"tt"->2),2)	   
     val rdd2 = sc.parallelize(List("bb"->1,"aa"->3,"dd"->3,"ss"->6),2)
     //设置两个rdd的分区相同,在进行join之前使用groupBykey()
     val gb1 = rdd1.groupByKey()
     val gb2 = rdd2.groupByKey()
     val joind: RDD[(String, (Int, Int))] = gb1.join(gb2)

    通过UI界面观察到,一个共有3个stage,虽然使用了两个shuffle算子,但是和使用一个join的stage相同
    从平行化到groupByKey是一个stage,这样就是两个stage,groupByKey到saveAsTextFile是一个stage
    rdd1经过groupByKey后,假设两个分区分别是P1:(aa,5)(aa,3) ,P2:(bb,5),(dd,6),(tt,2)
    rdd2经过groupByKey后,假设两个分区分别是P1:(aa,3), P2:(bb,1),(dd,3).(ss,6)
    在进行join时按key 进行join,不会发生shuffle
    在这里插入图片描述

    #第三种情况,两个rdd的分区数不同,在join之前进行groupByKey
     val rdd1 = sc.parallelize(List("aa"->5,"bb"->5,"dd"->6,"aa"->3"tt"->2),1)	   
     val rdd2 = sc.parallelize(List("bb"->1,"aa"->3,"dd"->3,"ss"->6),5)
     //设置两个rdd的分区不同相同,在进行join之前使用groupBykey()
     //注:在分区不同时进行join,最后在join时的分区,和rdd分区的数相同
     //这种情况下一共 会 产生1+1+5+5个task
     val gb1 = rdd1.groupByKey()
     val gb2 = rdd2.groupByKey()
     val joind: RDD[(String, (Int, Int))] = gb1.join(gb2)

    有stage的图可以看出来,分区数小的rdd,在join时发生shuffle,
    分区数大的rdd,在join时没有发生shuffle
    在这里插入图片描述

    #第四种情况,两个rdd的分区数不同,在join之前进行groupByKey,在join时从新指定分区
    val rdd1 = sc.parallelize(List("aa"->5,"bb"->5,"dd"->6,"aa"->3"tt"->2),1)	   
     val rdd2 = sc.parallelize(List("bb"->1,"aa"->3,"dd"->3,"ss"->6),5)
     //设置两个rdd的分区不同相同,在进行join之前使用groupBykey()
     //注:在分区不同时进行join,最后在join时的分区,和rdd分区的数相同
    
     val gb1 = rdd1.groupByKey()
     val gb2 = rdd2.groupByKey()
     val joind: RDD[(String, (Int, Int))] = gb1.join(gb2,6)
    // val joind: RDD[(String, (Int, Int))] = gb1.join(gb2,5)
     //val joind: RDD[(String, (Int, Int))] = gb1.join(gb2,6)

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    闲来无事研究研究.Net中的异步编程
    Sql Server 因为触发器问题导致数据库更新报错“在触发器执行过程中引发了错误,批处理已中止”的问题处理
    c# 连接Redis报错:WRONGTYPE Operation against a key holding the wrong kind of value:类型搞混弄出的错误
    VS2013 调试时出现“表达式计算器中发生内部错误”的问题解决办法
    WCF优化的几个常规思路
    UWP汉堡菜单
    C#注册系统全局快捷键
    CXF详细介绍
    hadoop默认3个核心配置文件说明
    在虚拟机配置hive
  • 原文地址:https://www.cnblogs.com/jeasonit/p/12019424.html
Copyright © 2020-2023  润新知