map和mapPartitions
map针对RDD中的每一个元素调用一次函数,而mapPartitions针对RDD中每个Partition调用一次函数,假设RDD有N个元素,有M个分区,那么map的函数的将被调用N次,而mapPartitions被调用M次。,因此在编写map和mapPartitions的函数时需要有一个概念,map传入的是RDD的一个元素,而mapPartitions传入的是RDD的一个分区。
如下可见mapFun和mappartitionFun的区别
def mapFun(x):
return x+2
def mappartitionFun(xlist):
return [x+2 for x in xlist]
def _main():
# set sparkcontext
conf = SparkConf().setMaster("local[*]").setAppName("My App")
sc = SparkContext(conf=conf)
sc.setLogLevel("ERROR")
rdd = sc.parallelize([1, 2, 3, 4, 5, 6])
# res = rdd.mapPartitions(mappartitionFun)
res = rdd.map(mapFun)
res.collect()
# stop spark
sc.stop()
两者对比
加入函数内存在数据库连接、文件创建关闭等操作,则map每次调用都会创建一次连接和文件句柄,导致性能十分低,而mapPartitions只在每个Partition中创建一次,效率高。但是mapPartitions会存在OOM问题,即内存溢出,例如当一个partition的数据量超出内存限制时一次性载入函数中会导致OOM,而map就不会存在这样的情况因为它每次处理一条数据,当内存不足时可以将以前处理好的数据从内存中垃圾回收,腾出空间。