一、RDD算子补充

1、mapPartitions
         mapPartitions的输入函数作用于每个分区, 也就是把每个分区中的内容作为整体来处理。   (map是把每一行)

mapPartitions一次处理一个分区的所有数据,而map算子一次处理分区中的一条数据,所以mapPartitions处理数据的速度比map快,如果RDD分区的数据很庞大,用mapPartitions容易造成内存溢出,

如果RDD分区数据量小,从而提升速度的角度考虑,可以使用mapPartitions算子。

JAVA实现:

scala实现:

2、mapPartitionsWithIndex

mapPartitionsWithIndex方法与mapPartitions方法功能类似

不同的是mapPartitionsWithIndex还会对原始分区的索引进行 追踪, 这样就能知道分区所对应的元素 。  方法的参数为一个函数, 函数的输入为整型索引和迭代器。

JAVA实现:

  1. public static void mapPartitionsWithIndex(){
  2. SparkConf conf=new SparkConf().setAppName("mapPartitionsWithIndex").setMaster("local");
  3. JavaSparkContext sc=new JavaSparkContext(conf);
  4. //模拟数据并创建初始RDD
  5. JavaRDD<String> datas = sc.parallelize(Arrays.asList("张三","李四","李思","李斯"),2);
  6. JavaRDD<String> result = datas.mapPartitionsWithIndex(new Function2<Integer, Iterator<String>, Iterator<String>>() {
  7.  
  8. /**
  9. *
  10. */
  11. private static final long serialVersionUID = 1L;
  12.  
  13. public Iterator<String> call(Integer index, Iterator<String> datass) throws Exception {
  14. // TODO Auto-generated method stub
  15. ArrayList<String> arrayList = new ArrayList<String>();
  16. while(datass.hasNext()){
  17. String info="第"+index+"分区的数据:"+datass.next();
  18. arrayList.add(info);
  19. }
  20. return arrayList.iterator();
  21. }
  22. }, false);
  23.  
  24. List<String> collect = result.collect();
  25. for(String a:collect){
  26. System.out.println(a);
  27. }
  28.  
  29. sc.close();
  30. }  

scala实现:

  1. def mapPartitionsWithIndex: Unit ={
  2. val conf=new SparkConf().setAppName("cogroup").setMaster("local")
  3. val sc=new SparkContext(conf)
  4. val a=sc.parallelize(Array("liu","zhao","wang","li"),2)
  5. val result=a.mapPartitionsWithIndex((x,y)=>{
  6. val arraybuffer=ArrayBuffer[String]()
  7. while(y.hasNext){
  8. val info=x+" "+y.next()
  9. arraybuffer+=info
  10. }
  11. arraybuffer.iterator
  12. })
  13. result.foreach(x=>{
  14. println(x)
  15. })
  16. sc.stop()
  17. }

  

3、mapValues运算

可以针对RDD内每一组(key,value)进行运算, 并且产生另外一个RDD。
           例如: 将每一组( key,value) 的value进行平方运算
           kvRDD1.mapValues(x => x*x).collect

4、union
               union方法( 等价于“++”) 是将两个RDD取并集, 取并集的过程中不 会把相同元素去掉。  union操作是输入分区与输出分区多对一模式。

scala实现:

  1. def union: Unit ={
  2. val conf=new SparkConf().setAppName("union").setMaster("local")
  3. val sc=new SparkContext(conf)
  4. val rdd1=sc.parallelize(Array((1,2),(2,3),(3,4)))
  5. val rdd2=sc.parallelize(Array((1,2),(4,3),(5,4)))
  6. val result=rdd1.union(rdd2)
  7. result.foreach(x=>{
  8. println(x._1+" "+x._2)
  9. })
  10. sc.stop()
  11. }
    结果:

1 2
2 3
3 4

1 2
4 3
5 4

  5、distinct
          distinct方法是将RDD中重复的元素去掉, 只留下唯一的RDD元素。

6、intersection交集运算
           intersection方法可以获取两个RDD中相同的数据

  1. def intersection: Unit ={
  2. val conf=new SparkConf().setAppName("intersection").setMaster("local")
  3. val sc=new SparkContext(conf)
  4. val rdd1=sc.parallelize(Array((1,2),(2,3),(3,4)))
  5. val rdd2=sc.parallelize(Array((1,2),(4,3),(5,4)))
  6. val result=rdd1.intersection(rdd2).foreach(x=>{
  7. println(x._1+" "+x._2)})
  8. sc.stop()
  9. }  

7、subtract差集运算
          intRDD1.subtract(intRDD2).collect()
          intRDD1是List(3,1,2,5,5), 扣除intRDD2 List(5,6)重复的部分5, 所 以结果是(1,2,3)

  1. //把rdd1 rdd2中的相同项,从rdd1中去除掉
    def subtract: Unit ={
  2. val conf=new SparkConf().setAppName("intersection").setMaster("local")
  3. val sc=new SparkContext(conf)
  4. val rdd1=sc.parallelize(Array((1,2),(2,3),(3,4)))
  5. val rdd2=sc.parallelize(Array((1,2),(4,3),(5,4)))
  6. rdd1.subtract(rdd2).foreach(x=>{
  7. println(x._1+" "+x._2)})
  8. sc.stop()
  9. }

  8、aggregateByKey
         reduceByKey认为是aggregateByKey的简化版
         aggregateByKey最重要的一点是, 多提供了一个函数, Seq Function

可以控制如何对每个partition中的数据进行先聚合, 类似于mapreduce中的map-side combine, 然后才是对所有partition中的数据进行全局聚合
         aggregateByKey, 分为三个参数:
                    第一个参数是, 每个key的初始值
                    第二个是个函数, Seq Function, 如何进行shuffle map-side的本地聚合
                    第三个是个函数, Combiner Function, 如何进行shuffle reduce-side的全局聚合

Java实现:

scala实现:

  1. //在调用aggregateByKey算子时,第二、三两个参数时(这两个参数传入的是函数),运用柯里化的方式,不需要给函数传参
  2. def aggregateByKey: Unit ={
  3. val conf=new SparkConf().setAppName("aggregateByKey").setMaster("local")
  4. val sc=new SparkContext(conf)
  5. val lines=sc.textFile("file:///home/hadoop/product.txt")
  6. def seq(num1:Int,num2:Int):Int={
  7. num1+num2
  8. }
  9. def comb(num1:Int,num2:Int):Int={
  10. num1+num2
  11. }
  12. lines.map(x=>(x,1)).aggregateByKey(0)(seq,comb).foreach(x=>{
  13. println(x._1+" "+x._2)
  14. })
  15. }

  9、cartesian
          cartesian, 中文名笛卡尔乘积
         比如说两个RDD, 分别有10条数据, 用了cartesian算子以后,两个RDD的每一条数据都会和另外一个RDD的每一条数据执行一次join,最终组成了一个笛卡尔乘积

  1. def cartesian: Unit ={
  2. val conf=new SparkConf().setAppName("cartesian").setMaster("local")
  3. val sc=new SparkContext(conf)
  4. val rdd1=sc.parallelize(Array((1,2),(2,3),(3,4)))
  5. val rdd2=sc.parallelize(Array((1,2),(4,3),(5,4)))
  6. rdd1.cartesian(rdd2).foreach(x=>{
  7. println(x._1+" "+x._2)
  8. })
  9. }

(1,2) (1,2)
(1,2) (4,3)
(1,2) (5,4)
(2,3) (1,2)
(2,3) (4,3)
(2,3) (5,4)
(3,4) (1,2)
(3,4) (4,3)
(3,4) (5,4)

  10、coalesce
        coalesce算子, 功能是将RDD的partition缩减, 将一定量的数据压缩到更少的partition中去。建议的使用场景, 配合filter算子使用
       使用filter算子过滤掉很多数据以后, 比如30%的数据, 出现了很多partition中的数据不均匀的情况

此时建议使用coalesce算子, 压缩rdd的partition数量, 从而让各个partition中的数 据都更加的紧凑 
       缺点:只能减少分区数,不能增加分区数

11、repartition
          repartition算子, 用于任意将rdd的partition增多或者减少

与coalesce不同之处在于, coalesce仅仅能将rdd的partition变少, 但是 repartition可以将rdd的partiton变多
         一个很经典的场景, 使用Spark SQL从hive中查询数据时  Spark SQL会根据hive对应的hdfs文件的block数量来决定加载出来的数据rdd 中有多少个partition,这里的partition数量, 是我们根本无法

设置的

有时候可能自动设置的partition数量过少, 导致我们后面的算子的运行特别慢    此时就可以在Spark SQL加载hive数据到rdd之后, 立即使用repartition算子, 将rdd的partition数量变多

  1. def repartition: Unit ={
  2. val conf=new SparkConf().setAppName("cartesian").setMaster("local")
  3. val sc=new SparkContext(conf)
  4. val a=sc.parallelize(Array("liu","zhao","wang","li","lll","aa"),3)
  5. val result=a.coalesce(2)//通过 coalesce减少分区
    // val result=a.repartition(4) 通过repartition增加 或者减少分区数
  6. result.mapPartitionsWithIndex((x,y)=>{
  7. val arr=ArrayBuffer[String]()
  8. while(y.hasNext){
  9. val info=x+" "+y.next()
  10. arr+=info
  11. }
  12. arr.iterator
  13. }).foreach(x=>println(x))
  14. }

  

补充:1、map:一次处理分区中的一条数据

mapPartitions:一次处理分区中的所有数据

mapPartitionsWithIndex:一次处理分区中的所有数据 ,并且返回分区的索引,索引从0开始

注意:如果RDD分区中的数据体量比较大,用mapPartitions或者mapPartitionsWithIndex进行计算,有可能出现内存溢出(OOM)

如果RDD分区数据体量比较小,此时为了提高数据计算的效率,可以使用mapPartitions或mapPartitionsWithIndex进行计算

RDD 算子补充的更多相关文章

  1. RDD算子

    RDD算子 #常用Transformation(即转换,延迟加载) #通过并行化scala集合创建RDD val rdd1 = sc.parallelize(Array(1,2,3,4,5,6,7,8 ...

  2. RDD算子、RDD依赖关系

    RDD:弹性分布式数据集, 是分布式内存的一个抽象概念 RDD:1.一个分区的集合, 2.是计算每个分区的函数 ,    3.RDD之间有依赖关系 4.一个对于key-value的RDD的Partit ...

  3. spark教程(四)-SparkContext 和 RDD 算子

    SparkContext SparkContext 是在 spark 库中定义的一个类,作为 spark 库的入口点: 它表示连接到 spark,在进行 spark 操作之前必须先创建一个 Spark ...

  4. Spark性能调优-RDD算子调优篇(深度好文,面试常问,建议收藏)

    RDD算子调优 不废话,直接进入正题! 1. RDD复用 在对RDD进行算子时,要避免相同的算子和计算逻辑之下对RDD进行重复的计算,如下图所示: 对上图中的RDD计算架构进行修改,得到如下图所示的优 ...

  5. Spark中普通集合与RDD算子的sortBy()有什么区别

    分别观察一下集合与算子的sortBy()的参数列表 普通集合的sortBy() RDD算子的sortBy() 结论:普通集合的sortBy就没有false参数,也就是说只能默认的升序排. 如果需要对普 ...

  6. Spark RDD算子介绍

    Spark学习笔记总结 01. Spark基础 1. 介绍 Spark可以用于批处理.交互式查询(Spark SQL).实时流处理(Spark Streaming).机器学习(Spark MLlib) ...

  7. 大数据入门第二十二天——spark(二)RDD算子(2)与spark其它特性

    一.JdbcRDD与关系型数据库交互 虽然略显鸡肋,但这里还是记录一下(点开JdbcRDD可以看到限制比较死,基本是鸡肋.但好在我们可以通过自定义的JdbcRDD来帮助我们完成与关系型数据库的交互.这 ...

  8. 大数据入门第二十二天——spark(二)RDD算子(1)

    一.RDD概述 1.什么是RDD RDD(Resilient Distributed Dataset)叫做分布式数据集,是Spark中最基本的数据抽象,它代表一个不可变.可分区.里面的元素可并行计算的 ...

  9. RDD算子的使用

    TransformationDemo.scala import org.apache.spark.{HashPartitioner, SparkConf, SparkContext} import s ...

随机推荐

  1. docker简单使用+django+uwsgi+nginx项目部署

    使用docker 搭建 centos7 环境: 主机环境:windows 10专业版 一.安装docker Hub.docker.com官网下载 docker for windows 安装完成后,任务 ...

  2. Zookeeper-----Zookeeper概述

    一:Zookeeper的概念? ZooKeeper是一种分布式协调服务,用于管理大型主机.在分布式环境中协调和管理服务是一个复杂的过程.ZooKeeper通过其简单的架构和API解决了这个问题.Zoo ...

  3. fetch上传文件报错的问题(multipart: NextPart: EOF)

    技术栈 后台: gin(golang) 前端: react+antd+dva 问题 前端这边使用fetch发送http请求的时候,后端解析formData报错: multipart: NextPart ...

  4. Linux内核学习笔记(3)-- 进程的创建和终结

    一. 进程创建: Unix 下的进程创建很特别,与许多其他操作系统不同,它分两步操作来创建和执行进程: fork() 和 exec() .首先,fork() 通过拷贝当前进程创建一个子进程:然后,ex ...

  5. leetcode个人题解——#49 Group Anograms

    思路:利用c++ stl的map来实现关键字匹配, 遍历strs容器类,对其中每一个string进行按字典序排序后,查找是否存在这样一个键,如不存在,存储该键,并将str[i]作为键映射的第一个元素: ...

  6. ASP.NET MVC - 启动创建项目,未能加载错误

    VS2012以常规方式创建一ASP.NET MVC internet 项目.创建后F5启动项目,遇一错误: 未能加载文件或程序集“MySql.Web.v20, Version=6.9.4.0, Cul ...

  7. Python Pygame(5)绘制基本图形

    最近很火一些简单图形构成的小游戏,这里介绍一些绘制图形的函数. 1.绘制矩形 rect(Surface,color,Rect,width=0) 第一个参数指定矩形绘制到哪个Surface对象上 第二个 ...

  8. 第八次作业psp

    psp 进度条 代码累积折线图 博文累积折线图 psp饼状图

  9. 随机生成30道四则运算-NEW

    补充:紧跟上一个随机生成30道四则运算的题目,做了一点补充,可以有真分数之间的运算,于是需要在原来的基础上做一些改进. 首先指出上一个程序中的几个不足:1.每次执行的结果都一样,所以不能每天给孩子出3 ...

  10. POJ 3258(二分求最大化最小值)

    题目链接:http://poj.org/problem?id=3258 题目大意是求删除哪M块石头之后似的石头之间的最短距离最大. 这道题目感觉大致代码写起来不算困难,难点在于边界处理上.我思考边界思 ...