[英]Spark Scala: mapPartitions in this use case
我在阅读有关map和mapPartitions之间的差异的内容很多。 我仍然有一些怀疑。 事情是在阅读之后,我决定在代码中更改mapPartitions
的map
函数,因为显然mapPartitions
比map
更快。
我的问题是要确定我的决定在以下情况下是否正确( 注释显示了先前的代码 ):
val reducedRdd = rdd.mapPartitions(partition => partition.map(r => (r.id, r)))
//val reducedRdd = rdd.map(r => (r.id, r))
.reduceByKey((r1, r2) => r1.combineElem(r2))
// .map(e => e._2)
.mapPartitions(partition => partition.map(e => e._2))
我在想对吗? 谢谢!
就您而言,mapPartitions应该没有任何区别。
mapPartitions与地图
当我们要对每个分区进行一些通用计算时,mapPartitions很有用。 范例-
rdd.mapPartitions{
partition =>
val complicatedRowConverter = <SOME-COSTLY-COMPUTATION>
partition.map {
row => (row.id, complicatedRowConverter(row) )
}
}
在上面的示例中,我们正在创建一个complicatedRowConverter
RowConverter函数,该函数是从一些昂贵的计算中衍生而来的。 此功能对于整个RDD分区都是相同的,我们不需要一次又一次地重新创建它。 做同一件事的另一种方法可以是-
rdd.map { row =>
val complicatedRowConverter = <SOME-COSTLY-COMPUTATION>
(row.id, complicatedRowConverter(row) )
}
}
这将很慢,因为我们不必要为每行运行此语句val complicatedRowConverter = <SOME-COSTLY-COMPUTATION>
。
就您而言,每个分区都没有任何预计算或其他任何内容。 在mapPartition中,您只需遍历每行并将其映射到(row.id, row)
。
因此,这里的mapPartition不会受益,您可以使用简单的map。
tl; dr mapPartitions
在这种情况下会很快。
考虑功能
def someFunc(row): row {
// do some processing on row
// return new row
}
假设我们正在处理100万条记录
我们最终将其称为someFunc
100万。
创建了无序的1m虚拟函数调用和其他内核数据结构以进行处理
我们将其写为
mapPartition { partIter =>
partIter.map {
// do some processing on row
// return new row
}
}
没有虚拟功能,请在此处进行上下文切换。
因此, mapPartitions
将更快。
另外,就像@ moriarity007的答案中提到的那样,在决定要使用的运算符之间时,我们还需要考虑操作涉及的对象创建开销。
另外,我建议使用数据帧转换和操作来进行处理,从而使计算速度更快,因为Spark催化剂可以优化您的代码,并且还可以利用代码生成的优势。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.