RDD转换算子
RDD 的两种算子:转换算子和行动算子。
RDD 根据数据处理方式的不同将算子整体上分为 Value 类型、双 Value 类型和 Key-Value 类型。
算子实际上是一些函数,用于数据处理。
Value类型
map
将处理的数据逐条进行映射转换,这里的转换可以是类型的转换,也可以是值的转换。
如果没有dataRDD2.collect().foreach(println),就不会输出结果,这句话也不能放在sparkContext.stop()后面,否则会报错,出现下面图片中的问题
因为SparkContext
是 Spark 的核心组件,负责与 Spark 集群进行通信,一旦它被关闭,就不能再用来执行任何任务。
mapPartitions
用于分区和映射操作。
map 和 mapPartitions 的区别:
数据处理角度
Map 算子是分区内一个数据一个数据的执行,类似于串行操作。而 mapPartitions 算子是以分区为单位进行批处理操作。
功能的角度
Map 算子主要目的将数据源中的数据进行转换和改变。但是不会减少或增多数据。MapPartitions 算子需要传递一个迭代器,返回一个迭代器,没有要求的元素的个数保持不变,所以可以增加或减少数据
性能的角度
Map 算子因为类似于串行操作,所以性能比较低,而是 mapPartitions 算子类似于批处理,所以性能较高。但是 mapPartitions 算子会长时间占用内存,那么这样会导致内存可能不够用,出现内存溢出的错误。所以在内存有限的情况下,不推荐使用。使用 map 操作。
mapPartitionsWithIndex
flatMap
用于扁平化后再映射,适用于嵌套数据的处理。(算子也称之为扁平映射。)
map和flatMap的区别:
map会将每一条输入数据映射为一个新对象。
flatMap包含两个操作:会将每一个输入对象输入映射为一个新集合,然后把这些新集合连成一个大集合。
glom
groupBy
用于根据指定规则进行分组,分区不变但数据可能重新组合。
一个组的数据在一个分区中,但是并不是说一个分区中只有一个组
filter
用于根据指定规则进行筛选过滤,分区不变但数据分布可能不均衡。
前两个结果是RDD1的,后两个结果是RDD2的
sample
用于根据指定规则抽取数据,可以设置放回与否及抽取几率。
distinct
用于去重操作,可以指定分区数。
coalesce
coalesce和下面的 repartition 函数,用于调整分区数量。
coalesce:缩减分区,用于提高小数据集的执行效率。
repartition
repartition:扩充分区或缩减分区,调整分区数量。
该操作内部其实执行的是 coalesce 操作,参数 shuffle 的默认值为 true。无论是将分区数多的RDD 转换为分区数少的 RDD,还是将分区数少的 RDD 转换为分区数多的 RDD,repartition操作都可以完成,因为无论如何都会经 shuffle 过程。
sortBy
用于排序操作,可以指定排序函数、升序降序及分区数量。
双Value类型
intersection
用于求两个 RDD 的交集,返回原始数据。
union
用于求两个 RDD 的并集,不进行去重。
subtract
用于求两个 RDD 的差集,以原RDD为主去掉重复元素。
zip
用于将两个 RDD 按照位置进行配对,组成键值对形式。
键值对:键和值可以是不同的数据类型,通过zip操作可以组成键值对形式的数据。
Key-Value类型
partitionBy
将数据按照指定 Partitioner 重新进行分区。Spark 默认的分区器是 HashPartitioner
groupByKey
将数据源的数据根据 key 对 value 进行分组
reduceByKey
可以将数据按照相同的 Key 对 Value 进行聚合
reduceByKey 和 groupByKey 的区别:
从 shuffle 的角度:reduceByKey 和 groupByKey 都存在 shuffle 的操作,但是 reduceByKey可以在 shuffle 前对分区内相同 key 的数据进行预聚合(combine)功能,这样会减少落盘的数据量,而 groupByKey 只是进行分组,不存在数据量减少的问题,reduceByKey 性能比较高。
从功能的角度:reduceByKey 其实包含分组和聚合的功能。GroupByKey 只能分组,不能聚合,所以在分组聚合的场合下,推荐使用 reduceByKey,如果仅仅是分组而不需要聚合。那么还是只能使用 groupByKey
aggregateByKey
将数据根据不同的规则进行分区内计算和分区间计算