一.Spark中的算子总结(原理)
Spark算子
1).Transformations ,转换算子,懒执行,需要Action类算子触发。
map/mapToPair,flatMap,filter,reduceByKey,sample,sortBy/sortByKey,groupByKey,join,leftOutJoin,rightOuterJoin,fullOuterJoin,distinct,union,intersection,subtract,repartition,coalesce,zip,zipWithIndex,mapPartitions,
mapPartitionWithIndex,cogroup,mapValues,aggreagateByKey,combineByKey
2).Action,行动算子,触发Action类算子执行。Spark应用程序中(Spark Application)有一个Action算子就有了一个job。
take,frist,foreach,count,collect,reduce,foreachPartition,countByKey,countByValue
3).持久化算子。
a).cache
默认将数据持久化到内存,cache()=persist()=persist(StorageLevel.MEMORY_ONLY)
b).persist
可以手动指定数据持久化级别。
MEMORY_ONLY
MEMORY_ONLY_SER
MEMORY_AND_DISK
MEMORY_AND_DISK_SER
"_2"代表有副本数,尽量避免使用"DISK_ONLY"级别。
c).checkpoint
将数据可以持久化到磁盘,指定的checkpoint目录中,切断checkpointRDD之前的依赖关系,使之后的RDD依赖于checkpoint目录中的数据。需要设置checkpoint路径。
RDD lineage 非常长,每一个RDD之间逻辑复杂,计算耗时。对一个RDD进行checkpoint之前最好先cache下。
注意:
a).cache和persist注意事项:
i).cache和persist是懒执行,需要Action算子触发。
ii).对一个RDD进行cache/persist之后,可以赋值给一个变量,下次直接使用这个变量就是使用的持久化的数据。
iii).cache/persist之后不能紧跟Action类算子。
b).checkpoint执行流程:
i).Spark任务执行完成之后,会从后往前回溯,找到CcheckpointRDD做标记。
ii).回溯完成之后,重新计算标记RDD的数据,将数据放入checkpoint目录中。
iii).切断RDD之间的依赖关系。
————————————————————————————————————————————————————————
二.算子实例
package com.bjsxt
import org.apache.spark.SparkConf
import org.apache.spark.SparkContext
import scala.collection.mutable.ListBuffer
object Suanzi {
def main(args: Array[String]): Unit = {
val conf=new SparkConf().setAppName("test").setMaster("local");
val sc=new SparkContext(conf)
val rdd2=sc.parallelize(Array(
"love1","love2","love3","love4",
"love5","love6","love7","love8",
"love9","love10","love11","love12"
),3)
rdd2.foreach(println)
println("_________________________________--")
/**
* repartition重新分区
* 增加分区
* 是一个shuffle类的算子
*/
val repartition1=rdd2.repartition(5)
repartition1.foreach(println)
println("+++++++++++++++++++++++++++++++++++++")
/**
* repartition重新分区
* 减少分区
* 是一个shuffle类的算子
*/
val repartition2=rdd2.repartition(1)
repartition2.foreach(println)
/**
* Coalesce
* 可以增多,也可以减少分区
* 底层有shuffle,但是需要设置,默认是false关闭的
*
*/
println("##########################################")
val coalesce1=rdd2.coalesce(6, false)
coalesce1.foreach(println)
/**
* Coalesce
* 可以增多,也可以减少分区
* 底层有shuffle,但是需要设置,默认是false关闭的
*
*/
println("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%")
val coalesce2=rdd2.coalesce(6, true)
coalesce2.foreach(println)
/**
* Coalesce
* 可以增多,也可以减少分区
* 底层有shuffle,但是需要设置,默认是false关闭的
*
*/
println("PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP")
val coalesce3=rdd2.coalesce(2, true)
coalesce3.foreach(println)
println("*****************************************************")
/**
* mapPartitionsWithIndex
* 根据索引进行分区
*/
val mapPartitionsWithIndex = rdd2.mapPartitionsWithIndex((index,iter)=>{
val list=ListBuffer[String]()
while(iter.hasNext){
val next=iter.next()
println("parallelize index=["+index+"],value=["+next+"]")
list.+=(next)
}
list.iterator
},false).collect()
println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
/**
* reduce,将value的值进行累计求和
*/
val rdd1=sc.parallelize(Array(("a",200),("b",200),("a",300),("d",400),("a",200),("b",200),("a",300),("d",400)))
val result=rdd1.reduce((t1,t2)=>{
val key=t1._1+"~"+t2._1
val value=t1._2+t2._2
(key,value)
})
println(result)
println("?????????????????????????????????????????????????")
/**
* countbyvalue
* 根据value值不同进行求和计算
*/
val result1=rdd1.countByValue()
result1.foreach(println)
/**
* countbykey
* 根据value值不同进行求和计算
*/
println("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^")
val result2=rdd1.countByKey()
result2.foreach(println)
/**
* groupByKey
* 按照key的值不同进行分组
* 将value的值放在一起
*/
println("""""""""""""""""""""""""""""""""""""""""""""""""")
rdd1.groupByKey().foreach(println)
/**
* zip的意思就是合并成(k,v)格式
* 即第一个rdd的值为key,第二个RDD的值为value
*/
println("zip$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$")
val rdd3=sc.parallelize(Array(
"love1","love2","love3","love4",
"love5","love6","love7","love8",
"love9","love10","love11","love12"
))
val rdd4=sc.parallelize(Array(
"love1","love2","love3","love4",
"love5","love6","love7","love8",
"love9","love10","love11","love12"
))
val zip=rdd3.zip(rdd4)
zip.foreach(println)
/**
* zipWithIndex
*/
println("parallelize##########@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
val parallelize=sc.parallelize(Array(
"love1","love2","love3","love4",
"love5","love6","love7","love8",
"love9","love10","love11","love12"
),3)
val zipWithIndex= parallelize.zipWithIndex()
zipWithIndex.foreach(println)
/**
* mapPartitionsWithIndex和coalesce的混合使用
*/
println("mapPartitionsWithIndex和coalesce的混合使用")
val mapPartitionsWithIndex1 = rdd3.mapPartitionsWithIndex((index,iter)=>{
val list=ListBuffer[String]()
while(iter.hasNext){
val next=iter.next()
println("parallelize index=["+index+"],value=["+next+"]")
list.+=(next)
}
list.iterator
},false)
val coalesce=mapPartitionsWithIndex1.coalesce(7,true)
val result0=coalesce.mapPartitionsWithIndex((index,iter)=>{
val list=ListBuffer[String]()
while(iter.hasNext){
val next=iter.next()
println("parallelize index=["+index+"],value=["+next+"]")
list.+=(next)
}
list.iterator
},true).collect()
result0.foreach(println)
}
}
用心做事,只为方便你我,鼓励一下我呗!
https://blog.csdn.net/wyqwilliam/article/details/81394666
https://blog.csdn.net/wyqwilliam/article/details/81367412
https://blog.csdn.net/wyqwilliam/article/details/81355340
https://blog.csdn.net/wyqwilliam/article/details/81332216
https://blog.csdn.net/wyqwilliam/article/details/81289934
https://blog.csdn.net/wyqwilliam/article/details/81289550
https://blog.csdn.net/wyqwilliam/article/details/81156731
https://blog.csdn.net/wyqwilliam/article/details/81149154
https://blog.csdn.net/wyqwilliam/article/details/81149152
https://blog.csdn.net/wyqwilliam/article/details/81141437
https://blog.csdn.net/wyqwilliam/article/details/81140139
https://blog.csdn.net/wyqwilliam/article/details/81139875
————————————————————————————————————————————————————————
Repartitions算子:
重新分区
重新分区,可以增多分区,可以减少分区
是一个有shuffle类的算子
重新分区,可以增多分区,可以减少分区
是一个有shuffle类的算子
Coalesce也是重新分区,可以增多,也可以减少分区,还可以有一个重载的方法
可以产生shuffle,也可以不产生shuffle,默认是不产生shuffle的
Repartition底层封装的是coalesce
Coalesce丛小的分区到大的分区,同时不让产生shuffle,这样是不起作用的。
增多分区经常repartition
减少分区经常用coalesce
用coalesce,同时不设定true产生shuffle,这样子是不产生分区的。
Repartition重新分区,可多可少,默认有shuffle
coalesce重新分区,可多可少,可以设定分区是否产生shuffle,coalesce(numpartition,shuffle=true/false),默认是false
由少的分区到多的分区,不让产生shuffle,是不起作用的
Mappartition with index
Groupbykey:
将tuple类型的list转换成用(K,V)格式的RDD用parallelizepares
依据key的值,将所有的value的值放在一起。
zipwithIndex:转换成(k,v)格式的RDD
Zip就是将两个RDD压缩成一个RDD
Tuple类型的RDD也可以压缩成k,v
Groupbykey
Reduce:累加求总数
Countbykey:数一数相同的key有几个,按照pairRDD,统计相同的key有几个
Countbyvalue,可以作用到(k,v)格式的RDD上,也可以作用在非(K,V)格式的RDD上