1.RDD Transformations介绍:
RDD Transformations操作是在RDD上执行时的Spark操作,。它会导致一个或多个新RDD。由于RDD本质上是不可变的,因此转换总是在不更新现有RDD的情况下
创建新的RDD,因此,这会创建RDD族谱。RDD谱系也称为RDD运算符图或RDD依赖图。
RDD Transformations操作的两个特点是,在调用Spark RDD上的action操作之前,不会执行任何Transformations操作;由于RDD是不可变的,因此对其进行
任何Transformations操作都会导致产生新的RDD,而当前的RDD保持不变;
2.RDD Transformation有两种类型
(1)Narrow Transformation,称为窄转换,窄转换是基于窄依赖(narrow dependencies)进行的RDD转换。所谓窄依赖是指:父RDD的每个分区最多被儿子RDD的
一个分区使用。产生窄转换的函数有:map,filter,distinct,union,基于分区的jion等。窄转换的优点是高效,因为窄转换通常可以在同一个节点上完成,省
去了集群中节点之间的数据传输,并且由于父RDD的每个分区只会至多有一个子RDD的分区,在计算子RDD的分区时,计算过程不会有任何浪费。
Functions such as map(), mapPartition(), flatMap(), filter(), union() are some examples of narrow transformation
(2)Wider Transformation,宽转换是基于宽依赖(wide dependencies)进行的RDD转换。所谓宽依赖是指:父RDD的每个分区都可能被子RDD的多个分区使用。也就
是说,计算单个分区中的记录所需的数据可能存在父RDD的多个分区中。所以,宽转换会发生shuffle过程,有时候把宽转换也称为:shuffle transformations。
由于父RDD的分区数据被多个子RDD分区依赖,这样的话,在计算某个子RDD的分区时,需要计算父RDD的分区数据,但计算出来的父RDD的分区数据不会全部给子RDD使
用,也就造成了计算资源的浪费。导致宽转换的函数有:groupByKey,reduceByKey等。
Functions such as groupByKey(), aggregateByKey(), aggregate(), join(), repartition() are some examples of a wider transformations.
总之,Wider Transformation由于会需要shuffle过程,要比Narrow Transformation使用的资源更多。
3.例子-对test.txt进行Count Word
spark = SparkSession.builder\
.appName('SparkByExamples.com')\
.master("local[3]")\
.getOrCreate()
rdd = spark.sparkContext.textFile("test.txt")
- flatMap()
# flatMap() Transformation : 将原rdd打平,返回一个新的rdd
# collect() : Return a list that contains all of the elements in this RDD.
rdd2 = rdd.flatMap(lambda x: x.split(' '))
print(rdd2.collect())
- map()
# map() Transformation : 使用map()转换进行任何复杂的操作,例如添加列,更新列等,映射转换的输出将始终具有与输入相同的记录数。
# 在我们的单词计数示例中,我们将为每个单词添加一个值为1的新列,RDD的结果为PairRDDFunctions,其中包含很多键值对
rdd3 = rdd2.map(lambda x: (x, 1))
print(rdd3.collect())
- filter()
# filter() Transformation : 过滤RDD中的记录
# 过滤所有以“ a”开头的单词。返回的rdd4中都是以a开头的key
rdd4 = rdd3.filter(lambda x: x[0].startswith("a"))
print(rdd4.collect())
- reduceByKey()
# reduceByKey() Transformation : 将按照key先进行分组,然后每个组中的每个键的值会按照给定的特定方法计算
from operator import add
rdd5 = rdd4.reduceByKey(add)
print(rdd5.collect())
- sortByKey()
# sortByKey() Transformation : 用于对key上的RDD元素进行排序。
# 首先将rdd5中的key-value调换位置,然后排序
rdd6 = rdd5.map(lambda x: (x[1], x[0])).sortByKey()
- foreach()
# Action foreach(function) : Applies a function to all elements of this RDD
rdd6.foreach(print)
- repartition()
print("rdd6-partition count:", rdd6.getNumPartitions())
# repartition() : 设置rdd的分区数,该方法默认shuffle开启了
reparRdd = rdd.repartition(4)
print("re-partition count:", reparRdd.getNumPartitions())
# Action - count() : Return the number of elements in this RDD.
print("Count : ", rdd6.count())
打印结果: