join算子

join:

val rdd1 =sc.parallelize(List(("spark",1),("hadoop",1),("spark",2),("hadoop",2),("hive",2)))

 sc.parallelize(List(("spark",3),("hive",3),("spark",4),("hadoop",2)))

------->d.RDD[(String, (Int, Int))

这个有点类似

val  rdd0 = sc.flatMapValues(List("a"Array(1,2,3),("b",Array(4,5,6))))

----> (a,1),(a,2),(a,3)(b,4),(b,5),(b,6)

cogroup实现join的功能,

1.通过cogroup 实现局部分组聚合,好全局分组聚合从而得到(以Spark为例,list1中("spark"(1,2)),)

list2中("spark",3),完成区内聚合

2.通过flatmapValue----> ("spark",((1,2),3)) 然后遍历 t._.1iterator 和t._2.iterator 如果同时都存在组返回所以最后得出的结果为

("spark",(1,3)) ("spark",(2,3))

 

  //join,leftJoin,rightjoin,fulljoin
    //join底层默认的cogroup,cogroup用的是hashPartitioner,如果没有指定分区器,则默认为2个分区器
    //
    val conf = new SparkConf().setAppName("JoinDemo").setMaster("local[*]")
    val sc = new SparkContext(conf)

    val rdd1 = sc.parallelize(List(("spark",1), ("hadoop", 1), ("spark", 2), ("hive", 2),("flink", 2)), 2)

    val rdd2 = sc.parallelize(List(("spark", 3), ("hive", 3), ("hadoop", 4)), 2)

    //通过cogroup实现join类似的功能,从而了解join底层源码的工作原理
    val rdd3: RDD[(String, (Iterable[Int], Iterable[Int]))] = rdd1.cogroup(rdd2)
    val rdd4: RDD[(String, (Int, Int))] = rdd3.flatMapValues(t => {
      for (x <- t._1.iterator; y <- t._2.iterator) yield (x, y)
    })
    rdd4.saveAsTextFile("out3-join")
    

leftOutJoin


val conf = new SparkConf().setAppName("JoinDemo").setMaster("local[*]")
val sc = new SparkContext(conf)

val rdd1 = sc.parallelize(List(("spark",1), ("hadoop", 1), ("spark", 2), ("hive", 2),("flink", 2)), 2)

val rdd2 = sc.parallelize(List(("spark", 3), ("hive", 3), ("hadoop", 4)), 2)

val rdd: RDD[(String, (Int, Option[Int]))] = rdd1.leftOuterJoin(rdd2)

//使用cogroup实现类似leftOuterJoin的功能
val rdd3: RDD[(String, (Iterable[Int], Iterable[Int]))] = rdd1.cogroup(rdd2)
//Int来自于第一个RDD的value,Option[Int]来自于第二个RDD的value,如果有就是some,如果没有就none
val rdd4: RDD[(String, (Int, Option[Int]))] = rdd3.flatMapValues(t => {
  if (t._2.nonEmpty) {
    t._1.map((_, None))
  } else {
    for (x <- t._1.iterator; y <- t._2.iterator) yield (x, Some(y))
  }
})
rdd4.saveAsTextFile("out-leftjoin")

 

 

rightOuterJoin

    val conf = new SparkConf().setAppName("JoinDemo").setMaster("local[*]")
    val sc = new SparkContext(conf)

    val rdd1 = sc.parallelize(List(("spark",1), ("hadoop", 1), ("spark", 2), ("hive", 2),("flink", 2)), 2)

    val rdd2 = sc.parallelize(List(("spark", 3), ("hbase", 3), ("hadoop", 4)), 2)

    //val rdd: RDD[(String, (Option[Int], Int))] = rdd1.rightOuterJoin(rdd2)
    //使用cogroup实现类似rightOuterJoin的功能
    val rdd3: RDD[(String, (Iterable[Int], Iterable[Int]))] = rdd1.cogroup(rdd2)

    val rdd4: RDD[(String, (Option[Int], Int))] = rdd3.flatMapValues(t => {
      if (t._1.isEmpty) {
        t._2.map((None, _))
      } else {
        for (x <- t._1.iterator; y <- t._2.iterator) yield (Some(x), y)
      }
    })
    rdd4.saveAsTextFile("out-rightjoin")

  }

fullOuterJoin

 


    val conf = new SparkConf().setAppName("FullOuterJoinDemo").setMaster("local[*]")
    val sc = new SparkContext(conf)

    val rdd1 = sc.parallelize(List(("spark",1), ("hadoop", 1), ("spark", 2), ("hive", 2),("flink", 2)), 2)

    val rdd2 = sc.parallelize(List(("spark", 3), ("hbase", 3), ("hadoop", 4)), 2)

    //val rdd: RDD[(String, (Option[Int], Option[Int])] = rdd1.fullOuterJoin(rdd2)
    //使用cogroup实现类似rightOuterJoin的功能
    val rdd3: RDD[(String, (Iterable[Int], Iterable[Int]))] = rdd1.cogroup(rdd2)

    val rdd4: RDD[(String, (Option[Int], Option[Int]))] = rdd3.flatMapValues{
      case (i1, Seq()) => i1.iterator.map(x => (Some(x), None))
      case (Seq(), i2) => i2.iterator.map(y => (None, Some(y)))
      case (i1, i2) => for(a <- i1.iterator; b <- i2.iterator) yield (Some(a), Some(b))
    }
    rdd4.saveAsTextFile("out-fulljoin")

 

collect

    val conf = new SparkConf().setAppName("CollectDemo").setMaster("local[*]")
    val sc = new SparkContext(conf)
    val rdd1 = sc.parallelize(List(1,2,3,  4,5,6), 2)

    val rdd2: RDD[Int] = rdd1.map(_ * 10)
    //底层执行数据操作的是在executor里,然后把执行完成的数据返回到Driver端,
    //在调用runjob的时候,数据已经*10完成,
    //runjob是传入rdd,计算的逻辑函数,从第0 个分区一直算到最后一个分区
    


    val res: Array[Int] = rdd2.collect()

 

面试题:    如果collect的数据特别大会出现什么情况,spark只会collect一部分数据,Driver端收集多少数据根Drive内存有关系,占一个百分比,

如果超过这个内存的百分比,那么就会不再收集,

面试:   把设计好的数据是在Driver端写,还是在executor里面写,

在executor里面写,因为,在executor里面写.可以在多个Task,可以并行写,增加处理数据的效率,同时避免通过网络把数据收集到Driver端,如果收集到Driver端,必须要走网络,那么上传和处理的速度会大大减慢,

reduce;  是一个shuffle

底层传入rdd,局部聚合,全局聚合,与fold底层逻辑相似,只不过fold多了一个初始值

 

val  rdd1 = Array((1,2,3),(4,5,6),2)

aggregate: rdd1.aggregate(100)(_+_,_+_)   最终结果为321

初始值在每个分区会使用一边,然后再全局分组聚合的时候也会执行一遍 

 foreach 在执行的时候是在executor里面打印的

foreachPartition()  可以将数据以分区的形式拿出来.

rdd1.foreachPartition(it=>{it.forach(println)}) ------>打印到executor里面了

//对于foreachPartition来说,底层就是传入一个函数,底层有一个函数,这个函数就是迭代器,然后把迭代器作为参数传入到你所应用到的函数中

rdd1.foreachPartition(it=>{

//建立数据库或者从连接池中取出连接

//对迭代器中的多条数据进行操作

对于foreach来说,底层就是当你传入函数时,就是一条调用一次,一条数据就返回iter,然后迭代器里面的数据,每一条都应用一下你 传入的函数,这两个都是Action,因为底层调用了sc,runJob

it.foreach(t=>{

//使用事先创建好的连接,写入到数据库(反复使用连接)

 

})

//关闭连接或将连接换回连接池

)}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值