算子从是否触发job的角度划分,可以分为Transformation算子和Action算子,Transformation算子不会产生job,是惰性算子,只记录该算子产生的RDD及父RDD的partiton之间的关系,而Action算子将触发job,完成依赖关系的所有计算操作。
算子是优化Spark计算框架的主要依据。
Transformations
下表列出了Spark支持的一些常见转换。有关详细信息,请参考RDD API文档(Scala、Java、Python、R)和成对RDD函数文档(Scala、Java)。
https://spark.apache.org/docs/latest/rdd-programming-guide.html#rdd-operations
https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.rdd.RDD
https://spark.apache.org/docs/latest/api/java/index.html?org/apache/spark/api/java/JavaPairRDD.html
Transformation | 含义 |
---|---|
map(func) | 通过函数func传递源的每个元素,返回一个新的分布式数据集 。 任何原RDD中的元素在新RDD中都有且只有一个元素与之对应。 |
flatMap(func) | 将原来 RDD 中的每个元素通过函数 f 转换为新的元素,并将生成的 RDD 的每个集合中的元素合并为一个集合,内部创建 FlatMappedRDD(this,sc.clean(func))。 |
mapPartitions(func) | 和map(func) 计算结果相同,一次取一个分区的数据,而map一次只取一条数据.func在类型为T的RDD上运行时必须是类型Iterator => Iterator.最终的RDD由所有分区经过输入函数处理后的结果合并起来的。 |
mapPartitionsWithIndex(func) | 类似于mapPartitions,但也为func提供了一个表示分区索引的整数值,因此在类型为T的RDD上运行时,func必须是类型(Int, Iterator) => Iterator. |
mapWith(func) | mapWith是map的另外一个变种,map只需要一个输入函数,而mapWith有两个输入函数。它将第一个函数的输出作为第二个函数的输入. |
filter(func) | 过滤算子,对每个元素应用func函 数, 返回值为true的元素在RDD中保留,返回值为 false 的元素将被过滤掉。内部实现相当于生成FilteredRDD(this,sc.clean(func))。 |
sample(withReplacement, fraction, seed) | 使用给定的随机数生成器种子对数据的一部分进行抽样,无论是否进行替换。withReplacement:是否放回(是否放回抽样分true和false);fraction:采样比例(fraction取样比例为(0, 1]);seed:用于指定的随机数生成器的种子(seed种子为整型实数)。 |
union(otherDataset) | 返回一个新数据集,该数据集包含源数据集中的元素和参数的联合。求并集,不去重。使用 union 函数时需要保证两个 RDD 元素的数据类型相同 |
intersection(otherDataset) | 返回一个新的RDD,其中包含源数据集中元素与参数的交集,并去重,且无序返回。 |
subtract(other: RDD[T]) | 求差集,返回在RDD中出现并且不在otherRDD中出现的元素,不去重。 |
distinct([numPartitions])) | 去重,返回包含源数据集的不同元素的新数据集。 |
groupByKey([numPartitions]) | 通过Key分组统计,当调用(K, V)对的数据集时,返回(K, Iterable)对的数据集。注意:如果您分组是为了对每个键执行聚合(如sum或average),那么使用reduceByKey或aggregateByKey将获得更好的性能。默认情况下,输出中的并行程度取决于父RDD的分区数量。您可以传递一个可选的numPartitions参数来设置不同数量的任务。 |
reduceByKey(func, [numPartitions]) | 聚合,两个值合并成一个值,( Int, Int V)to (Int, Int C),比如叠加。 |
aggregateByKey(zeroValue)(seqOp, combOp, [numPartitions]) | 在(K, V)对的数据集上调用时,返回(K, U)对的数据集,其中每个键的值使用给定的组合函数和中性的“零”值进行聚合。允许与输入值类型不同的聚合值类型,同时避免不必要的分配。与groupByKey类似,reduce任务的数量可以通过第二个可选参数进行配置。 |
sortByKey([ascending], [numPartitions]) | 当调用一个(K, V)对的数据集时,其中K实现了有序,返回一个(K, V)对的数据集,按照升序或降序的键排序,如布尔升序参数中指定的那样。 |
join(otherDataset, [numPartitions]) | 当调用(K, V)和(K, W)类型的数据集时,返回一个(K, (V, W))对的数据集,每个键的所有元素对都是这样。通过leftOuterJoin、righttouterjoin和fullOuterJoin支持外部连接。 |
cogroup(otherDataset, [numPartitions]) | 当调用类型为(K, V)和(K, W)的数据集时,返回一个(K, (Iterable, Iterable))元组的数据集。此操作也称为groupWith。 |
cartesian(otherDataset) | 当调用类型为T和U的数据集时,返回(T, U)对(所有元素对)的数据集。 |
pipe(command, [envVars]) | 通过shell命令(例如Perl或bash脚本)传输RDD的每个分区。RDD元素被写入进程的stdin,输出到stdout的行作为字符串的RDD返回。 |
coalesce(numPartitions,false) | 将RDD中的分区数量减少到numpartition。用于过滤大型数据集后更有效地运行操作。使用HashPartitioner。第一个参数为重分区的数目,第二个为是否进行shuffle,默认为false |
repartition(numPartitions) | 随机重新洗牌RDD中的数据,以创建更多或更少的分区,并在它们之间进行平衡。这总是对网络上的所有数据进行洗牌。 |
repartitionAndSortWithinPartitions(partitioner) | 根据给定的分区器重新划分RDD,并在每个结果分区中按键对记录排序。这比调用重分区然后在每个分区中进行排序更有效,因为它可以将排序推入shuffle机制。 |
cache() | 将 RDD 元素从磁盘缓存到内存。 相当于 persist(MEMORY_ONLY) 函数的功能。 |
persist(newLevel:StorageLevel) | 对RDD 进行缓存操作。数据缓存在哪里依据 StorageLevel 这个枚举类型进行确定。默认存储级别为MEMORY_ONLY。其他常见的有:MEMORY_AND_DISK,MEMORY_ONLY_SER ,MEMORY_AND_DISK_SER,DISK_ONLY,MEMORY_ONLY_2,MEMORY_AND_DISK_2,OFF_HEAP (experimental) |
Actions
下表列出了Spark支持的一些常见操作。参考RDD API文档(Scala、Java、Python、R),并对RDD函数doc (Scala, Java)进行详细的配对。
Action | 含义 |
---|---|
reduce(func) | 使用函数func(接受两个参数并返回一个)聚合数据集的元素。这个函数应该是交换的和结合的,这样才能并行地正确计算。函数实现:Some(iter.reduceLeft(cleanF)) |
collect() | 在驱动程序中以数组形式返回数据集的所有元素。这通常在过滤器或其他返回足够小的数据子集的操作之后非常有用。collect 相当于 toArray, 将分布式的 RDD 返回为一个单机的 scala Array 数组。 |
collectAsMap() | 对(K,V)型的RDD数据返回一个单机HashMap。 对于重复K的RDD元素,后面的元素覆盖前面的元素。 |
count() | 返回数据集中元素的数量/行数。 |
first() | 返回数据集的第一个元素(类似于take(1))。 |
top(n) | 返回前面n个最大元素,可以定义排序规则.top(num:Int)(implicit ord:Ordering[T]):Array[T] |
take(n) | 返回包含数据集的前n个元素的数组。 |
takeSample(withReplacement, num, [seed]) | 返回一个数组,该数组具有数据集的num元素的随机样本,可以替换也可以不替换,可以预先指定随机数生成器种子。 |
takeOrdered(n, [ordering]) | 使用RDD的默认顺序排序(升序)或自定义比较器返回RDD的前n个元素。 |
saveAsTextFile(path) | 将数据集的元素作为文本文件(或文本文件集)写入本地文件系统、HDFS或任何其他hadoop支持的文件系统的给定目录中。Spark将对每个元素调用toString,将其转换为文件中的一行文本。 |
saveAsSequenceFile(path) | (Java和Scala)将数据集的元素作为Hadoop SequenceFile在本地文件系统、HDFS或任何其他Hadoop支持的文件系统中的给定路径中写入。这在实现Hadoop可写接口的键值对的RDDs上是可用的。在Scala中,它还可以用于隐式转换为可写的类型(Spark包括对Int、Double、String等基本类型的转换)。 |
saveAsObjectFile(path) | (Java和Scala)使用Java序列化以简单的格式编写数据集的元素,然后使用SparkContext.objectFile()加载这些元素。 |
countByKey() | 只在类型(K, V)的RDDs上可用。返回一个(K, Int)对的hashmap,其中包含每个键的计数。 |
foreach(func) | 遍历数据集,对每个元素运行函数func。这通常是为副作用,如更新累加器或与外部存储系统交互。注意:修改foreach()之外的累加器以外的变量可能会导致未定义的行为。 |
Spark RDD API还公开了一些操作的异步版本,比如foreachAsync for foreach,它会立即向调用者返回一个futuresponse,而不是在操作完成时阻塞。这可用于管理或等待操作的异步执行。
图解所有RDD算子之间的关系
两个特殊变量
广播变量(broadcast):
其广泛用于广播Map Side Join中的小表,以及广播大变量等场景。这些数据集合在单节点内存能够容纳,不需要像RDD那样在节点之间打散存储。
Spark运行时把广播变量数据发到各个节点,并保存下来,后续计算可以复用。 相比Hadoop的distributed cache,广播的内容可以跨作业共享。 Broadcast的底层实现采用了BT机制。
accumulator变量:
允许做全局累加操作,如accumulator变量广泛使用在应用中记录当前的运行指标的情景。
注意foreach中累计变量的失效.