spark中RDD算子分类整理

一、transaction算子/action算子

spark的算子可以分为transaction算子以及action算子,变换/转换算子,这种变换并不触发提交作业,完成作业中间过程处理。就是transaction算子,相反执行这个RDD时会触发 SparkContext 提交 Job 作业,那么它就是action算子。transaction算子会懒执行,action会立即执行当前算子以及当前算子到以及之前懒执行的算子。那么spark为什么要采用这种方式呢?spark会将所有连续的懒执行的操作都不立即执行,而是根据执行计划组件出一个执行的DAG有向无环图,直到遇到action算子,真个DAG才真正去执行,这样的目的在于DAG执行的内部可以执行流水线优化(流水线优化下面部分介绍),减少shuffle。而不是一个一执行一落地,提高了spark的执行效率。那么哪些是action哪些是transformation算子呢?

1)Value数据类型的Transformation算子:

        一对一型:map/flatmap/mapPartition/glom()(这个方法将在同一分区的元素T转换成Array[T])

        多对一型:union(合并不去重)/cartesian 这两个算子有些像mysql中的方法,分区数方面是之前两个算子的分区数的加                            和与乘积结果,从内容上看一个是累加一个是乘积,而且笛卡尔是从RDD变成pariRDD,但是这种十分耗损                              内存千万慎用。intersection:这个算子取两者的交集并且去重

        多对多型:groupby算子,比如groupByKey按照key从多个分区又指向其他的多个分区

        输出分区为输入分区子分区集型:filter:过滤/distinct:去重/subtract:rdd1.subtract(rdd2):取的是左边有但是右边没有的部                              分/sample:抽样/takeSample这个返回的是一个数组,跟别的有点不太一样。

        cache类型:cache/persist算子

2)Key-Value数据类型的Transfromation算子

         一对一型:mapValues算子

        单个RDD聚集:reduceByKey/combineByKey(https://blog.csdn.net/dapanbest/article/details/81096279)/partitionBy(对RDD进行分区操作)

        两个RDD聚集:Cogroup算子

        连接:join算子/leftOutJoin和 rightOutJoin算子

 3)Action算子

        无输出:foreach算子

        HDFS:saveAsTextFile(按照分区保存与hdfs样式一样)/saveAsObjectFile(将RDD序列化成对象后保存起来)

        scala集合和数据类型:collect/

                                             collectAsMap(适用于K-V元素并且如果K重复后面覆盖前面)

                                             reduceByKeyLocally/

                                             lookup(适用于K-V,lookup(K);先看RDD中是否有分区器,从分区中找到结果。如果不包含分区                                                          器,则是暴力扫描。)

                                             count/top/

                                             reduce/fold/:num=sc.parallelize([1,2,3,4]),sum=num.reduce(lambda x,y: x+y);     

                                             num.fold(0,lambda x,y:x+y);两者都需要元素类型一致,第二个flod给了个初始值     

                                             aggregate:https://www.jianshu.com/p/15739e95a46e      

        

        

二、按照窄依赖/宽依赖

整个DAG的执行,其实就是处理一个RDD转化为另外一个RDD的过程,这个过程中父RDD和子RDD之间是有关系的,称之为子RDD对父RDD的依赖,这种依赖是通过在子RDD当中保存父类的血缘来实现的。RDD之间的依赖又分为窄依赖与宽依赖。窄依赖:父RDD中所有的分区都面向子RDD的一个分区,说白了就是一对一或者多对一。宽依赖:父RDD中有分区面向子RDD中的多个分区。就是一对多。窄依赖可以省略shuffle,而宽依赖则需要shuffle,因此窄依赖的效率也会很高。因此如果整个DAG中存在多个连续的窄依赖则可以将这些连续的窄依赖整合到一起连续执行,中间都不会shuffle,从而大大提高效率,这样的优化就称之为流水线优化。性能的提升关键就是减少shuffle。下面整理下窄依赖、宽依赖的算子

窄依赖: 太多了不一一列举了

宽依赖:会引起shuffle的其实可以分为几类算子

            第一类重分区算子,将RDD自定义重分区会引起shuffle,代表算子repartition、repartitionAndSortWithinPartitions、                         coalesce等,其中coalesce将shuffle参数设置为true的时候就是repartition算子

            第二类bykey类的操作,因为要对各个分区中的key进行聚合操作所以要保证集群上的所有节点上的相同key,一定是                       在同一个节点上进行处理的,那么这时候就会引起shuffle,代表算子reduceByKey、groupByKey、sortByKey、                        combineByKey,aggregateByKey,sortBy、takeOrdered等

             第三类join类的操作:比如join、cogroup等,cogroup :: 把两边RDD相同key的value值抽取出来,形成2个迭代器,一个                        是装第一个RDD的value值,另一个是装第二个RDD的value值,然后形成一个元组(key,(value1,value2)),key还是原                        来的key,value*是每个RDD的value值,是迭代器;join算子其实就是将 value1,value2两两操作,假设value1迭代器值                        为(1,2),value2迭代器为(2,3),那么join的结果为 (1,2),(1,3),(2,2),(2,3)
 

 

参考博文:

https://blog.csdn.net/weixin_38750084/article/details/82772271

https://blog.csdn.net/weixin_41624046/article/details/88065581

https://blog.csdn.net/jiangwlee/article/details/50774561

你可能感兴趣的:(spark)