spark day02+day03

Posted 不想写bug第n天

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了spark day02+day03相关的知识,希望对你有一定的参考价值。

    • 1.RDD相关操作

    • 构建RDD

  • 1.从已经存在集合

  • 2.已经存在外部数据源

  • 3.从已经存在rdd转换成一个新的rdd

    • RDD两大算子

  • 常用转换算子

  • transformation

  • map、flatmap、fillter、mappartitions、distinct

  • groupby、sortby、reducebykey、mapvalues

  • actions: toreach/foreachpartition

  • 转换算子和行动算子区别:

  • 转换算子返回一个数据集而行动算子返回一个具体值,如reduce算子是行动算子 而 reducebykey是转换算子

  • action算子会触发job执行

    • 1.transformation (转换算子)

  • 懒加载:不会立即执行 不会触发job

    • 1.filter(过滤)

  • 过程

  • 1. 条件表达式A1 = A.filter(Column condition)

  • 2. 自定义过滤函数A1 = A.filter(FilterFunction<T> func)

  • 3. 条件字符串A1 = A.filter(String condition)

  • 命令

val data = sc.parallelize(List(10,20,35,40))
val filterfunc = data.filter(x => x!=20).collect、

//结果:Array[Int] = Array(10, 35, 40)

    • 2.map相关算子

    • map
  • 一一映射 处理rdd里面每一个元素

  • 1.使用并行化集合创建RDD。

val data = sc.parallelize(List(10,20,30))
  • 2.应用map函数并传递执行所需的表达式。

val mapfunc = data.map(x => x+10)
//结果:Array[Int] = Array(20, 30, 40)
    • 1.makeRDD(设置分区)【调用parallelize算子】
  • 代码

val rdd = sc.parallelize(List(1, 2, 3, 4))
rdd.print(0)
//3  1  4  2

val rdd2 = sc.makeRDD(List(1, 2, 3, 4))
rdd2.print(0)
//1  2  3  4

    • 2.mapPartitions(内存优化)
  • map和mapPartitions

  • map每个一元素作用一个函数或者是算子

  • mapPartitions:有几个调用几次

    • 3.mapPartitonsWithIndex
  • 可以查看每个分区对应的数据

  • 代码

rdd.mapPartitionsWithIndex((index,partition)=>
   partition.map(x=> s"分区的下标$index,分区的元素$x")
).print(0)
//分区的下标0,分区的元素1
//分区的下标1,分区的元素3
//分区的下标0,分区的元素2
//分区的下标1,分区的元素4
    • 4.mapvalues
  • 针对kv类型进行操作 对v进行处理

rdd.map(x=>(x,1)).mapValues(x=>x+1).print(0)
//(3,2)
//(1,2)
//(4,2)
//(2,2)
    • 5.flatMap
  • 一一映射(压扁的)

  • flatmap = flatten + map

  • 举例:sc.parallelize(List(List(1,2),List(3,4))).collect

sc.parallelize(List(List(1,2),List(3,4))).map(x=> x.map(_*2)).collect

sc.parallelize(List(List(1,2),List(3,4))).flatMap(x=>x.map(_*2)).collect

  • sc.parallelize(List(List(1,2),List(3,4))).flatMap(x=>x.map(_*2)).print(0)

    • 3.other算子

    • 1.glom(数据形成数组)
  • 把每一个分区的数据形成数组

    • 2.sample(抽样)
  • 三个参数

  • withReplacement:表示抽出样本后是否在放回去,true表示会放回去,这也就意味着抽出的样本可能有重复

  • fraction:这是一个double类型的参数,0-1之间,eg:0.3表示抽出30%

  • 如果抽取不放回的场合:则表示数据源中每条数据被抽取的概率,

  • 如果抽取放回的场合:表示数据源中的每条数据被抽取的可能次数

  • seed:抽取数据时随机算法的种子,如果传递参数,则运行时每次抽取的数据是一样的,如果不传递参数,则每次运行时结果是不一样的。【一般无用】

 sc.parallelize(1 to 20).sample(false,0.4,20).print(0)

//11  5  14  15  17  19
    • 3.union(合并)
  • rdd1.union(rdd2)

scval rdd1 = sc.parallelize(1 to 3)
val rdd2 = sc.parallelize(2 to 5)
val rdd3 = rdd1.union(rdd2)
rdd3.print(0)

//结果  1 2 3 2 3 4 5 
    • 4.intersection(交集)
    val rdd1 = sc.parallelize(1 to 3)
    val rdd2 = sc.parallelize(2 to 5)
    rdd1.intersection(rdd2).print(0)

//结果 2  3
    • 5. intersection(差值)
val rdd1 = sc.parallelize(1 to 3)
val rdd2 = sc.parallelize(2 to 5)
rdd1.intersection(rdd2).print(1)

//结果 1
    • 6.distinct(去重)
  • 默认采用分区器:hash

元素 % 分区数 (List(4,4,4,5,5,5,6,6,6,7,8,9,10,10)

分区号:0 、元素是4、8 【4 % 4 == 0】

分区号:1 元素是5 、9

分区号:2 元素是6、10

分区号:3 元素是7

  • 代码

    val a = sc.parallelize(List(4,4,4,5,5,5,6,6,6,7,8,9,10,10))
    a.distinct().print(0)
    //7  9  5  4  6  8  10

    a.distinct(4).mapPartitionsWithIndex((index,partition)=>
      partition.map(x=> s"分区号:$index,元素是$x")
    ).print(0)
    //分区号:1,元素是9
    //分区号:0,元素是4
    //分区号:1,元素是5
    //分区号:0,元素是8
    //分区号:3,元素是7
    //分区号:2,元素是6
    //分区号:2,元素是10
    • 4.kv类型算子

    • 1.分组
    • 1.groupByKey(按照key进行分组)
  • 效率低、不灵活

  • 过程

按Key进行分组,List(("A",1),("B",2),("A",2),("B",3))

(B,(2, 3)) (A,(1, 2))
然后对key进行个数统计
# (A,2) # (B,2)
  • 代码

val arr7 = List(("A",1),("B",2),("A",2),("B",3))
val rdd33 = sc.parallelize(arr7)
val groupByKeyRDD = rdd33.groupByKey()
groupByKeyRDD.foreach(println)

//(A,CompactBuffer(1, 2))
//(B,CompactBuffer(2, 3))
    • 补充:顶聚合
  • 减少map端输出的数据量

仅对加和操作使用,无法对平均值使用

  • mapreduce

input map [combine] reduce output

  • 过程

  • map

(a,1) (a,1) (a,1) (b,1) (b,1)

  • combine:顶聚合 按照map端输出的key进行聚合数据

(a,3)

(b,2)

  • reduce

a,<1,1,1>

a,<1,1,1>

    • 2.groupby(自定义分组)
    val rdd6 = sc.parallelize(List("a", "a", "a", "a", "b", "b", "b"))
    rdd6.groupBy(x => x).print(0)
   // (b,CompactBuffer(b, b, b))
   // (a,CompactBuffer(a, a, a, a))

    val wc = sc.parallelize(List(("a", 1), ("a", 2), ("b", 2), ("c", 3)))
    wc.groupBy(x => x._1).print(0)
    //(b,CompactBuffer((b,2)))
    //(a,CompactBuffer((a,1), (a,2)))
    //(c,CompactBuffer((c,3)))
    • 3.reduceByKey

  • mapSideCombine = true+ func

  • distinct底层

  • map + reduceByKey + map 对key进行去重

    • 2.排序
    • 1.sortByKey(按照key排序)
val rdd5 = sc.parallelize(List(("tiantian", 15), ("luo", 18), ("lili", 12)))
rdd5.sortByKey().print(0)
rdd5.map(x => (x._2,x._1)).sortByKey(false).map(x => (x._2,x._1)).print(0)

    /**
     * (lili,12)
     * (tiantian,15)
     * (luo,18)
     * --------
     * (luo,18)
     * (tiantian,15)
     * (lili,12)
     */
    • 2.sortby(自定义排序)
val rdd5 = sc.parallelize(List(("tiantian", 15), ("luo", 18), ("lili", 12)),1)
rdd5.sortBy(x => x._2, false).print(0)

    /**
     * (luo,18)
     * (tiantian,15)
     * (lili,12)
     */
(List(("tiantian", 15), ("luo", 18), ("lili", 12)),1) 中的1:定义一个分区块
    • 5.join

  • join和 cogroup

  • 1.根据 key进行关联

  • 2. join返回值类型:

    • 1.join
    val t1 = sc.parallelize(List(("tiantian", 15), ("luo", 18), ("lili", 12)))
    val t2 = sc.parallelize(List(("tiantian", "辽宁"), ("luo", "内蒙"), ("lili", "广西")))
    t1.join(t2).print(0)

    /**结果
     * (tiantian,(15,辽宁))
     * (luo,(18,内蒙))
     * (lili,(12,广西))
     */
    • 2.cogroup
    val t1 = sc.parallelize(List(("tiantian", 15), ("luo", 18), ("lili", 12)))
    val t2 = sc.parallelize(List(("tiantian", "辽宁"), ("luo", "内蒙"), ("lili", "广西")))
    t1.cogroup(t2).print(0)

    /**结果
     * (tiantian,(CompactBuffer(15),CompactBuffer(辽宁)))
     * (luo,(CompactBuffer(18),CompactBuffer(内蒙)))
     * (lili,(CompactBuffer(12),CompactBuffer(广西)))
     */

    • 2.行动算子actions 【出发job执行的操作】

  • 触发作业的执行

  • 好处:更高效

  • 1.collect()

  • 2.foreach()

  • 1.控制台

  • 2.hdfs

  • 3.db

  • 3.foreachpartition()

  • 4.reduce()

  • 5.first() take()

  • first底层调用take算子

  • 6.top

  • 7.countbukey

    • 案例【排序】

  • 要求:按照商品的价格进行【desc】排序 如果价格相同 按照库存排序【asc】

  • 数据

商品名字 商品价格 库存数量
dior 300 1000
香奈儿 4000 2
螺蛳粉 20098
3090显卡200 10
  • 代码

def main(args: Array[String]): Unit = 
    val sc: SparkContext = ContextUtils.getSparkContext(this.getClass.getSimpleName)
    import org.example.sparkcore.function.ImplictAsRdd._

    val input = sc.parallelize(List("dior 300 1000", "YSL 350 500", "纪梵希 280 23"),1)

    val etlData: RDD[(String, Int, String)] = input.map(line => 
      val strings = line.split("\\t")
      val name = strings(0)
      val price = strings(1).toInt
      val cnt = strings(2)
      (name, price, cnt)
    )
    etlData.sortBy(x => (-x._2,x._3)).print(0)

    sc.stop()
  

//出错了 数组越界
  • 1

    • 案例【分组聚合】

  def main(args: Array[String]): Unit = 
    val sc: SparkContext = ContextUtils.getSparkContext(this.getClass.getSimpleName)
    import org.example.sparkcore.function.ImplictAsRdd._

    val Data = sc.parallelize(List("a,5,2", "b ,2,3", "c,3,8","a,1,99","b,8,2"))
    val eltData: RDD[(String,(Int,Int))] = Data.map(Line => 
      val strings = Line.split(",")
      val word: String = strings(0)
      val show = strings(1).toInt
      val  click= strings(2).toInt
      (word,(show,click))
    )
    eltData.reduceByKey((x,y)=>
      (x._1 + y._1, x._2 + y._2)
    ).print(0)

    sc.stop()
  

//(b,(8,2))
//(a,(6,101))
//(b ,(2,3))
//(c,(3,8))

以上是关于spark day02+day03的主要内容,如果未能解决你的问题,请参考以下文章

Note_Spark_Day02:Standalone集群模式和使用IDEA开发应用程序

自学it18大数据笔记-第三阶段Spark-day03——会持续更新……

Day03-02阿铭Linux-Linux磁盘管理

day03_02 集合操作

Spark Project中动态更改表中要查询的列

day03-自己实现Mybatis底层机制-02