目录
一.算子的分类
- 在Spark中,算子是指用于处理RDD(弹性分布式数据集)的基本操作。算子可以分为两种类型:转换算子和行动算子。
转换算子(lazy):
转换算子是将一个RDD转换为另一个RDD的操作,不会立即执行,而是创建一个新的RDD,以记录转换的方式和参数,然后等待后续的行动算子触发计算。
行动算子(no-lazy):
行动算子是触发计算并返回结果的操作。它们会立即对RDD进行计算,然后将结果返回给驱动程序或存储到文件系统等。
二.转换算子:
Value类型:
map
def map[U: ClassTag](f: T => U): RDD[U] = withScope
将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以是值的转换
map将原来RDD的每个数据项通过map中的用户自定义函数f映射转变为一个新的元素。源码中的map算子相当于初始化一个RDD,新RDD叫做MappedRDD
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4))
println(rdd.map(x => x * 2).collect().mkString(","))
sc.stop()
// 结果:2,4,6,8
mapPartitions
def mapPartitions[U: ClassTag](f: Iterator[T] => Iterator[U], preservesPartitioning: Boolean = false): RDD[U]
可以以分区为单位进行数据处理操作,这里的处理是指可以进行任意的处理,哪怕是过滤数据。但是会将整个分区的数据加载到内存中引用,处理完的数据是不会被释放掉,存在对象的引用,在内存较小,数据量较大的情况下会出现内存溢出(OOM)
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),2)
val dataRDD1: RDD[Int] = rdd.mapPartitions(
datas => {
//几个分区就会打印几次>>>>>>>>>>>>>
println(">>>>>>>>>>>>>")
datas.map(_*2)
}
)
println(dataRDD1.collect().mkString(","))
sc.stop()
//>>>>>>>>>>>>>
//>>>>>>>>>>>>>
//2,4,6,8
map与mapPartitions区别:
数据处理
map算子是分区内一个数据一个数据的执行
mapPartitions算子是以分区为单位进行批处理操作。
功能
map算子主要目的是将数据源中的数据进行转换和改变。不会减少或增多数据
mapPartitions算子需要传递一个迭代器,返回一个迭代器,没有要求元素的个数保持不变,可以增加或减少数据
性能
map算子类似于串行操作,性能较低
mapPartitions算子类似于批处理,性能较高。
mapPartitionsWithIndex
def mapPartitionsWithIndex[U: ClassTag](f: (Int, Iterator[T]) =>Iterator[U],preservesPartitioning: Boolean = false): RDD[U]
将待处理的数据以分区为单位发送到计算节点进行处理,这里的处理是指可以进行任意的处
理,哪怕是过滤数据,在处理时同时可以获取当前分区索引。
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),2)
// 获取数据与所对应的分区
val mapRdd: RDD[(Int, Int)] = rdd.mapPartitionsWithIndex(
(index, datas) => {
datas.map((index, _))
}
)
println(mapRdd.collect.mkString(","))
sc.stop()
flatMap
def flatMap[U: ClassTag](f: T => TraversableOnce[U]): RDD[U]
将处理的数据进行扁平化后再进行映射处理,所以算子也称之为扁平映射
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[List[Int]] = sc.makeRDD(List(List(1, 2), List(3, 4)))
val flatRdd: RDD[Int] = rdd.flatMap(
list => {
list
}
)
println(flatRdd.collect.mkString(",")) // 1,2,3,4
val rdd1: RDD[String] = sc.makeRDD(List("hello world", "hello spark"))
val flatRdd1: RDD[String] = rdd1.flatMap(
str => str.split(" ")
)
println(flatRdd1.collect.mkString(",")) //hello,world,hello,spark
sc.stop()
glom
def glom(): RDD[Array[T]]
将同一个分区的数据直接转换为相同类型的内存数组进行处理,分区不变
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4), 2)
val glomRdd: RDD[Array[Int]] = rdd.glom()
glomRdd.collect.foreach(data => println(data.mkString(",")))
sc.stop()
groupBy
**def groupBy[K](f: T => K)(implicit kt: ClassTag[K]): RDD[(K, Iterable[T])] **
将数据源中的每一个数据进行分组判断,根据返回的分组key进行分组,相同的key值的数据会放置一个组中。
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[Int] = sc.makeRDD(List(1, 2, 3, 4),2)
// groupby会将数据源中的每一个数据进行分组判断,根据返回的分组key进行分组,相同的key值的数据会放置一个组中。
val groupByRdd: RDD[(Int, Iterable[Int])] = rdd.groupBy(
_ % 2
)
groupByRdd.collect.foreach(println) // (0,CompactBuffer(2, 4))
//(1,CompactBuffer(1, 3))
val rdd1: RDD[String] = sc.makeRDD(List("hello","hi","spark","sqoop"),2)
//
val groupByRdd1: RDD[(String, Iterable[String])] = rdd1.groupBy(
_.substring(0, 1)
)
groupByRdd1.collect.foreach(println) //(h,CompactBuffer(hello, hi))
//(s,CompactBuffer(spark, sqoop))
sc.stop()
filter
**def filter(f: T => Boolean): RDD[T] **
将数据根据指定的规则进行筛选过滤,符合规则的数据保留,不符合规则的数据丢弃。当数据进行筛选过滤后,分区不变,但是分区内的数据可能不均衡,生产环境下,可能会出现数据倾斜。
val conf: SparkConf = new SparkConf().setMaster("local[*]").setAppName("RDD")
val sc: SparkContext = new SparkContext(conf)
val rdd: RDD[Int]