目录
Spark常用算子详解
1. mapPartitions
2. mapPartitionsWithIndex
3. getNumPartitions
4. partitions
5. foreachPartition
6. coalesce
7. repartition
8. union,zip,join
9. zipWithIndex,zipWithUniqueId
未完待续...
本文主要介绍工程中常用的Spark算子以及其用法。
//功能:遍历partition
param ://参数是一个函数
f :
param : Iterator[T] //函数参数是一个集合,代表一个partition的数据
return : Iterator[T] //返回值也是一个集合
遍历所有的partition。适用于单条处理开销太大的,批处理等场景。比如:遍历数据插入数据库的时候,给每个partition分配一个数据库链接,操作一批数据之后再销毁或者放回链接。
示例代码:
rdd.mapPartitions(x=>{
println("创建链接。。。")
x.foreach(x=>{
println("拼接SQL..."+x)
})
println("提交。。。")
x
}).count();
与上面mapPartitions类似只不过参数变成了(f:(Int,Iterator[T])=>Iterator[T])第一个参数是partition的ID,我们可以拿到partition的Id,查看数据都存放在那些RDD里面,常用于测试环境。
示例代码:
rdd.mapPartitionsWithIndex((index: Int, iterator: Iterator[Int]) => {
println("partitionId" + index);
iterator.foreach(println)
println("-------------")
iterator
}).count()
获得partition的数量
示例代码:
println(rdd.getNumPartitions)
获取所有的partition,返回值是一个Partition类型的数组
示例代码:
rdd.partitions.foreach(println)
功能:与mapPartition功能一样,只不过mapPartition是transformation类算子,而foreachPartition是action类算子
示例代码:
rdd.foreachPartition(x=>{
x.foreach(println)
})
def coalesce(numPartitions: scala.Int, shuffle: scala.Boolean = {
/* compiled code */
})(implicit ord: scala.Ordering[T] = {
/* compiled code */
}): org.apache.spark.rdd.RDD[T] = {
/* compiled code */
}
重新分区方法,参数numPartitions是分区数;shuffle 是否产生shuffle,true代表产生shuffle,false则不产生shuffle。
返回值:重新分区后的RDD。需要注意的是:
示例代码:
rdd.coalesce(2,true)
//如果分区数增多了而shuffle设置为false,那么分区数将不会改变
//分区数减少则不会产生shuffle,即便设置了shuffle为true。他会在逻辑上将数据合并
def repartition(numPartitions: scala.Int)(implicit ord: scala.Ordering[T] = {
/* compiled code */
}): org.apache.spark.rdd.RDD[T] = {
/* compiled code */
}
重新分区方法,参数是分区数,返回值是重新分区后的RDD
这个方法会产生shuffle,底层调用的是coalesce(numPartitions,true)
【示例代码】:
rdd.repartition(3)
union(other:RDD[T])是数据合并,返回一个新的数据集,由原数据集和otherDataset联合而成。
示例代码:
val rdd1 = sc.parallelize(1 to 3)
val rdd2 = sc.parallelize(4 to 6)
rdd1.union(rdd2).foreach(println)
res:
1
2
3
4
5
6
相较于union,zip(other:RDD[T]) 则是横向合并,针对相同位置进行合并,如果左右元素数量不同,报错!如果左右元素数量相同,分区数不一致,也会报错!
示例代码:
val rdd = sc.makeRDD(1 to 3, 2)
val rdd2 = sc.makeRDD(4 to 6, 2)
rdd.zip(rdd2).zip(rdd2).foreach(println)
res:
((1,4),4)
((2,5),5)
((3,6),6)
相同的,横向合并还有join算子,它是针对相同key进行合并。将输入数据集(K,V)和另外一个数据集(K,W)进行Join,得到(K, (V,W));该操作是对于相同K的V和W集合进行笛卡尔积操作;
zipWithIndex是将内容和索引作为二元组返回,不过他是将索引作为value,内容为key返回的。
示例代码:
val rdd = sc.makeRDD(1 to 3, 2)
rdd.zipWithIndex().foreach(println)
res:
(1,0)
(2,1)
(3,2)
可以使用swap将KV翻转:
rdd.zipWithIndex()
.map(_.swap)
.foreach(println)
res:
(0,1)
(1,2)
(2,3)
zipWithUniqueId