Performance ApacheSpark:map与mapPartitions?
Performance ApacheSpark:map与mapPartitions?,performance,scala,apache-spark,rdd,Performance,Scala,Apache Spark,Rdd,map和mapPartitions方法之间有什么区别?而flatMap的行为类似于map还是类似于mapPartitions?谢谢 (编辑) i、 e.两者之间的区别(无论是语义上还是执行方面)是什么 RDD的map和mapPartitions方法有什么区别 该方法通过应用函数将源RDD的每个元素转换为结果RDD的单个元素。将源RDD的每个分区转换为结果的多个元素(可能没有) flatMap的行为类似于map还是mapPartitions 两者都不适用于单个元素(如map)并生成结果的多个元素(
map
和mapPartitions
方法之间有什么区别?而flatMap
的行为类似于map
还是类似于mapPartitions
?谢谢
(编辑)
i、 e.两者之间的区别(无论是语义上还是执行方面)是什么
RDD的map和mapPartitions方法有什么区别
该方法通过应用函数将源RDD的每个元素转换为结果RDD的单个元素。将源RDD的每个分区转换为结果的多个元素(可能没有)
flatMap的行为类似于map还是mapPartitions
两者都不适用于单个元素(如map
)并生成结果的多个元素(如map分区
)。Imp.TIP:
每当你有重量级的初始化,应该做一次
对于许多RDD
元素,而不是每个RDD
元素一次,以及
初始化,例如从第三方创建对象
库,无法序列化(以便Spark可以跨
将群集连接到工作节点),使用mapPartitions()
而不是
map()
<代码>映射分区()提供了要完成的初始化
每个辅助任务/线程/分区一次,而不是每个RDD
数据一次
元素,请参见下文
问题2平面地图的行为是否类似于地图或地图分区 对。请参见
flatmap
的示例2。。这是不言自明的
问题1RDD的map
和mapPartitions
之间有什么区别
map
在每个元素级别上运行正在使用的功能,而
mapPartitions
在分区级别执行该功能
示例场景:如果我们在一个特定的RDD
分区中有100K个元素,那么当我们使用map
时,我们将触发映射转换使用的函数100K次
相反,如果我们使用mapPartitions
,那么我们将只调用一次特定函数,但我们将传入所有100K记录,并在一次函数调用中返回所有响应
由于map
多次在特定函数上工作,因此性能会有所提高,特别是如果函数每次都做一些昂贵的事情,而如果我们一次传入所有元素,它就不需要做这些事情(在map分区
的情况下)
地图
对RDD的每个项应用转换函数并返回
结果显示为一个新的RDD
列出变体
def映射[U:ClassTag](f:T=>U):RDD[U]
例如:
val a = sc.parallelize(List("dog", "salmon", "salmon", "rat", "elephant"), 3)
val b = a.map(_.length)
val c = a.zip(b)
c.collect
res0: Array[(String, Int)] = Array((dog,3), (salmon,6), (salmon,6), (rat,3), (elephant,8))
映射分区
这是一个专门的映射,每个分区只调用一次。
各个分区的全部内容都可以作为
通过输入参数的连续值流(Iterarator[T])。
自定义函数必须返回另一个迭代器[U]。合并
结果迭代器将自动转换为新的RDD。请
请注意,下面缺少元组(3,4)和(6,7)
由于我们选择的分区而导致的结果
preserveSpatiting
指示输入函数是否保留
分区器,它应该是false
,除非这是一对RDD和输入
函数不修改键
列出变体
def-mapPartitions[U:ClassTag](f:Iterator[T]=>Iterator[U],
preserveSpatiting:Boolean=false):RDD[U]
例1
val a = sc.parallelize(1 to 9, 3)
def myfunc[T](iter: Iterator[T]) : Iterator[(T, T)] = {
var res = List[(T, T)]()
var pre = iter.next
while (iter.hasNext)
{
val cur = iter.next;
res .::= (pre, cur)
pre = cur;
}
res.iterator
}
a.mapPartitions(myfunc).collect
res0: Array[(Int, Int)] = Array((2,3), (1,2), (5,6), (4,5), (8,9), (7,8))
例2
val x = sc.parallelize(List(1, 2, 3, 4, 5, 6, 7, 8, 9,10), 3)
def myfunc(iter: Iterator[Int]) : Iterator[Int] = {
var res = List[Int]()
while (iter.hasNext) {
val cur = iter.next;
res = res ::: List.fill(scala.util.Random.nextInt(10))(cur)
}
res.iterator
}
x.mapPartitions(myfunc).collect
// some of the number are not outputted at all. This is because the random number generated for it is zero.
res8: Array[Int] = Array(1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 5, 7, 7, 7, 9, 9, 10)
上述程序也可以使用flatMap编写,如下所示
示例2使用flatmap
val x = sc.parallelize(1 to 10, 3)
x.flatMap(List.fill(scala.util.Random.nextInt(10))(_)).collect
res1: Array[Int] = Array(1, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10)
结论:
mapPartitions
转换比map
更快,因为它只调用一次函数/partition,而不是一次/element
进一步阅读:地图:
映射与映射分区
Spark Map
Spark映射分区
地图:
地图转换
地图一次只能在一行上工作
映射在每个输入行之后返回
映射没有将输出结果保存在内存中
地图没有办法弄清楚然后结束服务
// map example
val dfList = (1 to 100) toList
val df = dfList.toDF()
val dfInt = df.map(x => x.getInt(0)+2)
display(dfInt)
映射分区:
映射分区转换
MapPartition一次在一个分区上工作
MapPartition在处理分区中的所有行后返回
MapPartition输出保留在内存中,因为它可以在处理特定分区中的所有行后返回
MapPartition服务可以在返回之前关闭
// MapPartition example
Val dfList = (1 to 100) toList
Val df = dfList.toDF()
Val df1 = df.repartition(4).rdd.mapPartition((int) => Iterator(itr.length))
Df1.collec()
//display(df1.collect())
有关更多详细信息,请参阅本文
希望这是有帮助的 谢谢-那么map是否会导致混乱(或者改变分区的数量)?它是否在节点之间移动数据?我一直在使用Maviges避免在节点之间移动数据,但不确定FLAPMAP是否会这样做。如果您查看源代码-并且,无论是“代码> MAP < /COD>和
val x = sc.parallelize(1 to 10, 3)
x.flatMap(List.fill(scala.util.Random.nextInt(10))(_)).collect
res1: Array[Int] = Array(1, 2, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10)
// map example
val dfList = (1 to 100) toList
val df = dfList.toDF()
val dfInt = df.map(x => x.getInt(0)+2)
display(dfInt)
// MapPartition example
Val dfList = (1 to 100) toList
Val df = dfList.toDF()
Val df1 = df.repartition(4).rdd.mapPartition((int) => Iterator(itr.length))
Df1.collec()
//display(df1.collect())