小记---------sparkRDD的Transformation 和 Action 及案例 原理解释

RDD :弹性分布式数据集;是一个容错的、并行的数据结构,可以让用户显式地将数据存储到磁盘或内存中,并控制数据的分区
 
RDD是Spark的核心数据结构,通过RDD的依赖关系形成Spark的调度顺序。所谓Spark应用程序,本质是一组对RDD的操作
 
RDD的两种创建方式
    从文件系统输入(如HDFS)创建
    从已存在的RDD转换得到新的RDD
 
RDD的两种操作算子
        Transformation(变换)Transformation类型的算子特点是lazy特性 ,(不是立刻执行,而是延迟执行)。也就是说从一个RDD变换为另一个RDD的操作需要等到Action操作触发时,才会真正执行。
       
         ·Action(行动)Action类型的算子会触发Spark提交作业,并将数据输出到Spark系统。
 
Transformation
Transformation(转换)
Meaning(含义)
map(func)
返回一个新的 distributed dataset(分布式数据集),它由每个 source(数据源)中的元素应用一个函数 func 来生成.
一对一的关系
filter(func)
返回一个新的 distributed dataset(分布式数据集),它由每个 source(数据源)中应用一个函数 func 且返回值为 true 的元素来生成.
过滤器(使用之后会过滤掉你不想要的)
flatMap(func)
与 map 类似,但是每一个输入的 item 可以被映射成 0 个或多个输出的 items(所以 func 应该返回一个 Seq 而不是一个单独的 item).
一对多的关系(处理完数据变多则使用该算子)
mapPartitions(func)
与 map 类似,但是单独的运行在在每个 RDD 的 partition(分区,block)上,所以在一个类型为 T 的 RDD 上运行时 func 必须是 Iterator<T> => Iterator<U> 类型.
map分区(就是分区的意思)
mapPartitionsWithIndex(func)
与 mapPartitions 类似,但是也需要提供一个代表 partition 的 index(索引)的 interger value(整型值)作为参数的 func,所以在一个类型为 T 的 RDD 上运行时 func 必须是 (Int, Iterator<T>) => Iterator<U> 类型.
把map分区后的数据赋予一个索引
sample(withReplacement, fraction, seed)
样本数据,设置是否放回(withReplacement), 采样的百分比(fraction)、使用指定的随机数生成器的种子(seed).
样本(取样)
union(otherDataset)
反回一个新的 dataset,它包含了 source dataset(源数据集)和 otherDataset(其它数据集)的并集.
intersection(otherDataset)
返回一个新的 RDD,它包含了 source dataset(源数据集)和 otherDataset(其它数据集)的交集.
distinct([numTasks]))
返回一个新的 dataset,它包含了 source dataset(源数据集)中去重的元素.
去重
groupByKey([numTasks])
在一个 (K, V) pair 的 dataset 上调用时,返回一个 (K, Iterable<V>) . Note: 如果分组是为了在每一个 key 上执行聚合操作(例如,sum 或 average),此时使用reduceByKey 或 aggregateByKey 来计算性能会更好. Note: 默认情况下,并行度取决于父 RDD 的分区数。可以传递一个可选的 numTasks 参数来设置不同的任务数.
通过key分组
reduceByKey(func, [numTasks])
在 (K, V) pairs 的 dataset 上调用时, 返回 dataset of (K, V) pairs 的 dataset, 其中的 values 是针对每个 key 使用给定的函数 func 来进行聚合的, 它必须是 type (V,V) => V 的类型. 像groupByKey 一样, reduce tasks 的数量是可以通过第二个可选的参数来配置的.
通过key计算(本身方法自带分组功能)
aggregateByKey(zeroValue)(seqOp, combOp, [numTasks])
在 (K, V) pairs 的 dataset 上调用时, 返回 (K, U) pairs 的 dataset,其中的 values 是针对每个 key 使用给定的 combine 函数以及一个 neutral "0" 值来进行聚合的. 允许聚合值的类型与输入值的类型不一样, 同时避免不必要的配置. 像 groupByKey 一样, reduce tasks 的数量是可以通过第二个可选的参数来配置的.
sortByKey([ascending], [numTasks])
在一个 (K, V) pair 的 dataset 上调用时,其中的 K 实现了 Ordered,返回一个按 keys 升序或降序的 (K, V) pairs 的 dataset, 由 boolean 类型的 ascending 参数来指定.
通过key进行排序(升序。降序)
join(otherDataset, [numTasks])
在一个 (K, V) 和 (K, W) 类型的 dataset 上调用时,返回一个 (K, (V, W)) pairs 的 dataset,它拥有每个 key 中所有的元素对。Outer joins 可以通过 leftOuterJoin, rightOuterJoin 和fullOuterJoin 来实现.
cogroup(otherDataset, [numTasks])
在一个 (K, V) 和的 dataset 上调用时,返回一个 (K, (Iterable<V>, Iterable<W>)) tuples 的 dataset. 这个操作也调用了 groupWith.
cartesian(otherDataset)
在一个 T 和 U 类型的 dataset 上调用时,返回一个 (T, U) pairs 类型的 dataset(所有元素的 pairs,即笛卡尔积).
pipe(command, [envVars])
通过使用 shell 命令来将每个 RDD 的分区给 Pipe。例如,一个 Perl 或 bash 脚本。RDD 的元素会被写入进程的标准输入(stdin),并且 lines(行)输出到它的标准输出(stdout)被作为一个字符串型 RDD 的 string 返回.
coalesce(numPartitions)
Decrease(降低)RDD 中 partitions(分区)的数量为 numPartitions。对于执行过滤后一个大的 dataset 操作是更有效的.
repartition(numPartitions)
Reshuffle(重新洗牌)RDD 中的数据以创建或者更多的 partitions(分区)并将每个分区中的数据尽量保持均匀. 该操作总是通过网络来 shuffles 所有的数据.
repartitionAndSortWithinPartitions(partitioner)
根据给定的 partitioner(分区器)对 RDD 进行重新分区,并在每个结果分区中,按照 key 值对记录排序。这比每一个分区中先调用 repartition 然后再 sorting(排序)效率更高,因为它可以将排序过程推送到 shuffle 操作的机器上进行.
 
     Actions(动作)
Action(动作)
Meaning(含义)
reduce(func)
使用函数 func 聚合 dataset 中的元素,这个函数 func 输入为两个元素,返回为一个元素。这个函数应该是可交换(commutative )和关联(associative)的,这样才能保证它可以被并行地正确计算.
collect()
在 driver 程序中,以一个 array 数组的形式返回 dataset 的所有元素。这在过滤器(filter)或其他操作(other operation)之后返回足够小(sufficiently small)的数据子集通常是有用的.
count()
返回 dataset 中元素的个数.
first()
返回 dataset 中的第一个元素(类似于 take(1).
take(n)
将数据集中的前 n 个元素作为一个 array 数组返回.
takeSample(withReplacement,num, [seed])
对一个 dataset 进行随机抽样,返回一个包含 num 个随机抽样(random sample)元素的数组,参数 withReplacement 指定是否有放回抽样,参数 seed 指定生成随机数的种子.
takeOrdered(n, [ordering])
返回 RDD 按自然顺序(natural order)或自定义比较器(custom comparator)排序后的前 n 个元素.
saveAsTextFile(path)
将 dataset 中的元素以文本文件(或文本文件集合)的形式写入本地文件系统、HDFS 或其它 Hadoop 支持的文件系统中的给定目录中。Spark 将对每个元素调用 toString 方法,将数据元素转换为文本文件中的一行记录.
saveAsSequenceFile(path) (Java and Scala)
将 dataset 中的元素以 Hadoop SequenceFile 的形式写入到本地文件系统、HDFS 或其它 Hadoop 支持的文件系统指定的路径中。该操作可以在实现了 Hadoop 的 Writable 接口的键值对(key-value pairs)的 RDD 上使用。在 Scala 中,它还可以隐式转换为 Writable 的类型(Spark 包括了基本类型的转换,例如 Int, Double, String 等等).
saveAsObjectFile(path) (Java and Scala)
使用 Java 序列化(serialization)以简单的格式(simple format)编写数据集的元素,然后使用SparkContext.objectFile() 进行加载.
countByKey()
仅适用于(K,V)类型的 RDD 。返回具有每个 key 的计数的 (K , Int)pairs 的 hashmap.
foreach(func)
对 dataset 中每个元素运行函数 func 。这通常用于副作用(side effects),例如更新一个 Accumulator(累加器)或与外部存储系统(external storage systems)进行交互。Note:修改除 foreach()之外的累加器以外的变量(variables)可能会导致未定义的行为(undefined behavior)。详细介绍请阅读 Understanding closures(理解闭包) 部分.
 
glom:将每个分区内的元素组成一个数组,分区不变     
 
 
union:合并同一数据类型元素,但不去重。合并后返回同类型的数据元素
 
Cartesian对输入RDD内的所有元素计算笛卡尔积
 
groupByKey:先将元素通过函数生成Key,元素转为“Key-Value”类型之后,将Key相同的元素分为一组
 
 
filter:对RDD中的元素进行过滤,过滤函数返回true的元素保留,否则删除
 
distinct:(去重)对RDD中的元素进行去重操作,重复的元素只保留一份。
subtract :(去除交集)对集合进行差操作,即RDD1中去除RDD1与RDD2的交集。 
sample:(取样)对RDD集合内的元素采样。 
takesample:与sample算子类似,可以设定采样个数。
 
案例: 以常见的Wordcount 程序为例
val lines = sc.textFile("spark.txt")  //通过textFile 此时spark.txt文件的数据是不会加载到内存中的 读取文件生成 lines RDD
val words = lines.flatMap(line => line.split(" "))  //通过flatMap算子(transformation操作)  生成words RDD
val pairs = words.map(word => (word , 1)) //通过map算子(transformation操作) 生成pairs RDD
val wordCount = pairs.reduceByKey(_+_)   //通过reduceByKey算子(transformation操作) 生成 WordCount RDD
//上面所有的其实都是lazy特性,所以至此其实程序还是没有任何操作的

//通过foreach算子(action操作)
//因为foreach是action操作,所以在此时,会触发一个spark job的执行,然后才会提交task到spark集群上去执行
wordCount.foreach(
wordCount => println(wordCount_1 + "appears" + wordCount_2 + "times")
)
//以上所有的代码都是在driver节点上执行,也就是执行我们自己编写的spark应用程序的节点,但是,在action执行之前,所有的transformation都是lazy的,
//不会立即执行,只有执行了action之后才会触发job,提交task到spark集群上, 进行实际的执行

在action操作执行完后,driver程序,实际会提交大量的task,到之前注册过来的worker上的executor上执行,
1.首先从hdfs上读取数据到worker的内存中
2.然后executor中的task,再针对hdfs对应的lines RDD 中的数据 , 依次执行我们定义的flatmap 、 map、reduceByKey等操作

spark中有一些特殊的算子,也就是特殊的transformation操作,比如groupByKey、sortByKey、reduceByKey等,其实只是针对特殊的RDD, 即包含 key-value对的RDD,而这种RDD中的元素,实际上是scala中的一种类型,即tuple2,也就是包含两个值的tuple。

在scala中,需要手动导入spark的相关隐式转换,import org.apache.spark.SparkContext._  。 然后对应包含tuple2的RDD,会自动隐式转换成PairRDDFunction,并提供reduceByKey等方法

 
 
 
posted @ 2019-10-12 11:03  于二黑  阅读(310)  评论(0编辑  收藏  举报