spark foreach与foreachPartition 详解

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37913435/article/details/84589536

spark foreach与foreachPartition

每个partition中iterator时行迭代的处理,通过用户传入的function对iterator进行内容的处理

一:foreach的操作:
Foreach中,传入一个function,这个函数的传入参数就是每个partition中,每次的foreach得到的一个rdd的kv实例,也就是具体的内容
这种处理你并不知道这个iterator的foreach什么时候结果,只能是在foreach过程中,你得到一条数据,就处理一条数据
由下面的代码可以看出,foreach操作是直接调用了partition中数据的foreach操作

def foreach(f:Unit):Unit=withScope{
	val cleanF=sc.clean(f)
	sc.runJob(this,(iter:Iterator[t])=> iter.foreach(cleanF))
}

示例说明:

val list = new ArrayBuffer()
Rdd.foreach(record=>
	list+=record
	if(list.size>=10000){
		list.flush
	}
)

上面的这段示例代码,如果会存在一个问题,迭代的最后,list的结果可能还没有达到10000条,这个时候,你在内部处理的flush部分就不会执行,也就是迭代的最后如果没有迭代达到10000条的数据就会丢失,所以在foreach中,一般就是拿到一条数据进行处理
Rdd.foreach(
record._1 == a
return)

foreachPartition 操作

这个函数也是根据传入的function进行处理,但是不同之处再有这里function传入的参数是一个partition对应数据的iterator
而不是直接使用iterator的foreach,这种情况下,如果是上面foreach的示例代码中list这个片段在这个actition中就能够正常的去处理

def foreachPartition(f:Iterrator[T]=>Unit):Unit=withScope{
	val cleanF=sc.clean(f)
	sc.runJob(this,(iter:Itertor[T]=>cleanF(iter)))
}

示例

val list = new ArrayBuffer
rdd.foreachPartition(it=>{
it.foreach(r=>{
list+=r
if(list.size>10000)
flush
})
if(list.size>0)
flush
})

关于源码

可以看到方法通过clean操作(清理闭包,为序列化和网络传输做准备),进行了一次匿名函数的封装
针对foreach方法,是我们的方法被传入了迭代器foreach(每个元素执行一次函数)
而对于foreachPartition方法是迭代器被传入了我们的方法(每个分区执行一次函数,我们获取迭代器后需要自行进行迭代处理)

展开阅读全文

没有更多推荐了,返回首页