spark算子大全glom_SparkCore的基础介绍和几种算子:

什么是RDD:

RDD叫做分布式数据集,是Spark最基本的数据抽象,代码中是一个抽象类,它代表的是一个不可变、可分区、里面的元素可并行计算的集合。

RDD里面封装的是计算逻辑。

RDD的属性:1. 一个分区(Partition),即数据集的基本组成单位。

2. 一个计算每个分区的函数。

3. RDD之间的依赖关系。

4. 一个Patitioner(即RDD的分片函数)

5. 一个列表,存取每个Partition的优先位置(preferred Location)

Rdd的特点:

Rdd表示只读的分区的数据集,对RDD的改动,只能进行RDD的转换操作,由一个RDD得到一个新的RDD,新的RDD包含了从其他RDD衍生所必需的信息,RDD之间存在依赖,RDD执行时按照血缘关系延时计算的,如果血缘关系较长,可以通过RDD的持久化切断血缘关系。

分区:

RDD逻辑上是分区的,每个分区的数据是抽象存在的,计算的时候会通过一个compute函数得到每个分区的数据,如果RDD是通过已有的文件系统构建,那么它的compute函数则只能读取指定文件系统中的数据,如果RDD是通过其他的RDD转换过来的,那么它的compute函数则是执行转换逻辑将其他RDD的数据进行转换。

这里生成的文件是八个,原因是因为它默认的cp是2个,但是它源码里面取得是num,Local*取得是你最大的内核数,我是8个内核,8和2比较,取最大值,生成了8个分区,所以8个内核并行计算,生成的文件是8个。

这里生成的2个文件,是因为它的源码里面取得是最小的分区数,它的min是2,所以生成的是2个文件。

如果你代码自定义分区数,一切以你代码为最高执行标准,所以你给多少它生成多少,特定情况除外,如min,你自定义2时,也许他会生成3个文件,

例子如:你文件是12345

你自定义为2个分区,可是它会生成三个,因为它采用是hadoopFile,有自己的切分规则,它除不尽,所以是三个。

算子:

Map算子:

Map算子是对每一条数据做操作,作用:是返回一个新的RDD,该RDD由每一个输入元素经过func函数转换后组成。

例子:

package m.s.k

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Spark_MapOper {

def main(args: Array[String]): Unit = {

//Local模式

//创建SparkConf对象,并部署计算环境

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("MapOper")

//创建SparkContext上下文对象

val sc: SparkContext = new SparkContext(conf)

//map算子

val listRdd: RDD[Int] = sc.makeRDD(1 to 10)

val mapRDD: RDD[Int] = listRdd.map(_*2)

//打印

mapRDD.collect().foreach(println)

}

}

MapPartitions(func)案例:

作用:类似于map,独立的在RDD的每一个分片上运行,因此在类型为T的RDD上运行时,func的函数类型必须是Iterator[T]=>Itertor[U],假如有N个元素,有M个分区,那么map的函数将被调用N次,而mapPartitions被调用M次,一个函数一次处理所有分区。

package m.s.k

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Spark_MapPartitiomsOper {

def main(args: Array[String]): Unit = {

//local模式

//创建Sparkconf对象,并部署计算机运行环境

val conf = new SparkConf().setMaster("local[*]").setAppName("MapPartitions")

//创建SparkContext上下文对象

val sc: SparkContext = new SparkContext(conf)

//MapPartitions

val listRDD: RDD[Int] = sc.makeRDD(1 to 10)

//mappartition可以对RDD里面所有的分区进行遍历

//MapPartition的效率优于map算子,减少了发送到执行器执行的交互次数,但它可能存在内存溢出

val mapPartition: RDD[Int] = listRDD.mapPartitions({

_.map(_* 2)

})

//打印

mapPartition.collect().foreach(println)

}

}

MapPartitionWithIndex(func)案例:

作用:类似于MapPartitions,但是func带有一个整数参数表示分片的索引值、因此,在类型为T的RDD上运行时、func的函数类型必须是Itertor[T]=>Itertor[U]

需求:创建一个RDD,使每个元素跟所在分区形成一个元组组成一个新的RDD

package m.s.k

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Spark_MapPartitionsWithIndex {

def main(args: Array[String]): Unit = {

//Local模式

//创建SparkConf,并部署计算环境

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("MapWithIndex")

//创建SparkContext上下文对象

val sc: SparkContext = new SparkContext(conf)

//MapPartitionsWithIndex

val listRDD: RDD[Int] = sc.makeRDD(1 to 10,2)

val tupleRDD: RDD[(Int, String)] = listRDD.mapPartitionsWithIndex {

case (num, datas) => {

datas.map((_, "分区号:" + num))

}

}

//打印

tupleRDD.collect().foreach(println)

}

}

所有算子里面的计算功能都是Executor来做的,如_*2计算,那怎么选择交给哪一个Executor呢,这个是由Driver决定的,它会判断哪一个Executoe计算会快一点。

FlatMap(func)案例:

作用:类似于map,但是每一个输入元素可以被映射为0或多个输出元素(所以func应该一个序列,而不是单一的元素)

需求:创建一个元素为1-5的RDD,运用flatMap创建一个新的RDD,新的RDD为原RDD的每个元素的2倍(2,4,6,8,10)

package m.s.k

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Spark_FlatMap {

def main(args: Array[String]): Unit = {

//Local模式

//创建SparkConf对象、并部署运行模式

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("FlatMapOper")

//创建SparkContext上下文对象

val sc: SparkContext = new SparkContext(conf)

//Flatmap算子

val listRDD: RDD[List[Int]] = sc.makeRDD(Array(List(1,2),List(3,4)))

val flatMapRDD: RDD[Int] = listRDD.flatMap(datas=>datas)

//打印

flatMapRDD.collect().foreach(println)

}

}

Map和MapPartition的区别:

1. map:每次处理一条数据

2. mappartition:每次处理一个分区的数据,当现在这个分区的数据处理完成之后,原分区的数据才能得到释放,可以导致OOM。

3. 开发介意:当你的内存空间足够大时,建议使用MapPartition,以提高效率。

glom的案例:

作用:将每一个分区形成一个数组(就是把每个分区的数据放到一个数组里面),形成新的RDD类型时:RDD[Array[T]]

需求:创建一个4个分区的RDD,并将每个分区的数据放到一个数组

package m.s.k

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Spark_glomOper {

def main(args: Array[String]): Unit = {

//Local模式

//创建SparkConf,并部署计算运行环境

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("glomOper")

//创建SparkContext上下文对象

val sc = new SparkContext(conf)

//glom算子

val listRDD: RDD[Int] = sc.makeRDD(1 to 16,4)

val glomRDD: RDD[Array[Int]] = listRDD.glom()

//打印

glomRDD.collect().foreach(array=>{

println(array.mkString(","))

})

}

}

Group(func)案例:

作用:分组,按照传入函数的返回值进行分组,将相同的key对应的值放到一个迭代器。

需求:创建一个RDD,按照元素模以2的值进行分组。

package m.s.k

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Spark_GroupByOper {

def main(args: Array[String]): Unit = {

//Local模式

//创建SparkConf,部署计算

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("GroupByOper")

//创建上下文对象

val sc: SparkContext = new SparkContext(conf)

//GroupBy算子

val listRDD: RDD[Int] = sc.makeRDD(1 to 6)

//1:1,3,5

//0:2,4,6

//生成数据,按照指定的规则进行分组,分组后的数据形成了对偶元组(K-V):K表示分组的key,V表示分组的集合

val GroupByRDD: RDD[(Int, Iterable[Int])] = listRDD.groupBy(_%2)

//打印

GroupByRDD.collect().foreach(println)

}

}

Filet(func)案例:

作用:过滤,返回一个新的RDD,该RDD由经过func函数计算后返回值为true的输入元素组成。

package m.s.k

import org.apache.spark.rdd.RDD

import org.apache.spark.{SparkConf, SparkContext}

object Spark_FilterOper {

def main(args: Array[String]): Unit = {

//创建SparkConf对象,并部署计算环境

val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("FilterOper")

//创建SparkContext上下文对象

val sc = new SparkContext(conf)

//Filter算子过滤

val listRDD: RDD[Int] = sc.makeRDD(1 to 10)

val filterRDD: RDD[Int] = listRDD.filter(_%2==0)

//打印

filterRDD.collect().foreach(println)

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值