spark 基于分区操作 mapPartitions

Spark分区方式详解 一、Spark数据分区方式简要              在Spark中,RDD(Resilient Distributed Dataset)是其最基本的抽象数据集,其中每个RDD是由若干个Partition组成。在Job运行期间,参与运算的Partition数据分布在多台机器的内存当中。这里可将RDD看成一个非常大的数组,其中Partition是数组中的每个元素,并且这些元素分布在多台机器中。... 阅读详情


基于分区对数据进行操作可以让我们避免为每个数据元素进行重复的配置工作。诸如打开数据库连接或者创建随机生成数等操作,都是我们应当避免的为每个元素都配置一遍的工作。Spark提供基于分区的map和foreach,让你的部分代码只对RDD的每个分区运行一次,这样可以帮助降低这些操作的代价。

当基于分区操作RDD时,Spark会为函数提供该分区中的元素的迭代器。返回值方面,也返回一个迭代器。

Spark 提供的基于分区操作的操作符,大概有:

mapPartitions()

mapPartitionsWithIndex()

foreachPartitions()

注意:foreachPartition 和 mapPartitions的分别,foreachPartition应该属于action运算操作,而mapPartitions是在Transformation中,所以是转化操作,此外在应用场景上区别是mapPartitions可以获取返回值,继续在返回RDD上做其他的操作,而foreachPartition因为没有返回值并且是action操作,所以使用它一般都是在程序末尾比如说要落地数据到存储系统中如mysql,es,或者hbase中,可以用它。当然在Transformation中也可以落地数据,但是它必须依赖action操作来触发它,因为Transformation操作是延迟执行的,如果没有任何action方法来触发,那么Transformation操作是不会被执行的,这一点需要注意。

下面分别举几个例子:

mapPartitionsWithIndex(), 和 mapPartitions() 类似,但是同时提供分区的索引

Demo

显示每个分区元素的分区索引
scala> val rdd1 =  sc.parallelize( List("yellow","red", "blue", "cyan", "black"), 3 )
rdd1: org.apache.spark.rdd.RDD[String] = ParallelCollectionRDD[101] at parallelize at <console>:26
scala> val mapped =   
     | rdd1.mapPartitionsWithIndex{
     | (index, iterator) => {
     |  println("Called in Partition -> " + index)
     | val myList = iterator.toList
     | myList.map(x => x + " -> " + index).iterator
     | }
     | }
mapped: org.apache.spark.rdd.RDD[String] = MapPartitionsRDD[102] at mapPartitionsWithIndex at <console>:29

scala> mapped.collect()
Called in Partition -> 0
Called in Partition -> 1
Called in Partition -> 2
res48: Array[String] = Array(yellow -> 0, red -> 1, blue -> 1, cyan -> 2, black -> 2)

mapPartitions():

与map方法类似,map是对rdd中的每一个元素进行操作,而mapPartitions(foreachPartition)则是对rdd中的每个分区的迭代器进行操作。

SparkSql或DataFrame默认会对程序进行mapPartition的优化。

Demo

实现将每个数字变成原来的2倍的功能

比如:输入2,结果(2,4)

使用map

scala> val a = sc.parallelize(1 to 9, 3)
a: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[103] at parallelize at <console>:26

scala> def mapDoubleFunc(a : Int) : (Int,Int) = {
     |     (a,a*2)
     | }
mapDoubleFunc: (a: Int)(Int, Int)

scala> val mapResult = a.map(mapDoubleFunc)
mapResult: org.apache.spark.rdd.RDD[(Int, Int)] = MapPartitionsRDD[104] at map at <console>:30

scala> println(mapResult.collect().mkString)
(1,2)(2,4)(3,6)(4,8)(5,10)(6,12)(7,14)(8,16)(9,18)

使用mapPartitions


scala> val a = sc.parallelize(1 to 9, 3)
a: org.apache.spark.rdd.RDD[Int] = ParallelCollectionRDD[105] at parallelize at <console>:26

scala> def doubleFunc(iter: Iterator[Int]) : Iterator[(Int,Int)] = {
     |     var res = List[(Int,Int)]()
     |     while (iter.hasNext)
     |     {
     |       val cur = iter.next;
     |       res .::= (cur,cur*2)
     |     }
     |     res.iterator
     |   }
doubleFunc: (iter: Iterator[Int])Iterator[(Int, Int)]

scala> val result = a.mapPartitions(doubleFunc)
result: org.apache.spark.rdd.RDD[(Int, Int)] = MapPartitionsRDD[106] at mapPartitions at <console>:30

scala> println(result.collect().mkString)
(3,6)(2,4)(1,2)(6,12)(5,10)(4,8)(9,18)(8,16)(7,14)

再举一个例子:

Demo

求平均值

不使用mapPartitions()求平均值

import org.apache.spark.rdd.RDD
val nums=sc.parallelize(List(1,2,3,4),3)

//不使用mapPartitions()求平均值
def reduce(x:(Int,Int),y:(Int,Int)):(Int,Int)={(x._1+y._1,x._2+y._2)}

def basicAvg(nums:RDD[Int]):Float={
  val sum = nums.map(x=>(x,1)).reduce(reduce)
  return sum._1 / sum._2.asInstanceOf[Float]
}

结果:

scala> basicAvg(nums)
res90: Float = 2.5

使用mapPartitions()求平均值

//使用mapPartitions()求平均值
def meanFunc(iter: Iterator[Int]) : Iterator[(Int,Int)]= {
     var x = 0
     var y = 0
     var res = List[(Int,Int)]()
     while (iter.hasNext)
     {
     val cur = iter.next
     x = x+cur
     y = y+ 1 
     }
     res .::= (x,y)
     res.iterator
}

//计算平均值
//如果没有import RDD,则需使用 org.apache.spark.rdd.RDD[Int]
def fastAvg(nums:RDD[Int]):Float={
	val sumCount = nums.mapPartitions(meanFunc).reduce(reduce)
  return sumCount._1 / sumCount._2.asInstanceOf[Float]
}

结果:

scala> fastAvg(nums)
res91: Float = 2.5

最后,需要注意一点,如果操作是iterator类型,我们是不能在循环外打印这个iterator的size,一旦执行size方法,相当于iterato就会被执行,所以后续的foreach你会发现是空值的,切记iterator迭代器只能被执行一次。




参考资料:

https://blog.youkuaiyun.com/u010454030/article/details/78897150

https://blog.youkuaiyun.com/wusuopubupt/article/details/53258067

https://blog.youkuaiyun.com/lsshlsw/article/details/48627737






Spark中mapPartitions算子详解介绍 上一节我们讲到如何使用map算子对RDD中的数据进行映射处理,但是map函数有个缺点就是不能够批处理,他是每次只处理一个元素,而本节使用的 `mapPartitions` 进行的类似于批处理,每次处理整个分区的数据。 阅读详情

相关推荐

第45课 Spark 2.0实战之Dataset:map、flatMap、mapPartitions、dropDuplicate、coalesce、repartition等

第45课 Spark 2.0实战之Dataset:map、flatMap、mapPartitions、dropDuplicate、coalesce、repartition等   package com.dt.spark200 import org.apache.spark.sql.SparkSession import scala.collection.mutable.ArrayBuffe

大模型与Agent智能体 1万+

Spark中mapPartitions使用

Spark中mapPartitions使用

Kverson 2385

3.ESP32S3 AP 配网开发实战:HTTP 与 WebSocket 协议实现

本文介绍了基于ESP32S3的AP配网实现方案,通过HTTP协议提供配网网页,利用WebSocket实现双向通信。详细解析了HTTP和WebSocket协议特点,阐述了SPIFFS文件系统存储HTML网页的方法,包括分区表配置、CMakeLists设置和代码实现。工程采用模块化设计,包含WiFi管理、Web服务器、IO扩展等组件,支持手机浏览器直接配网。测试验证了从AP热点连接到路由器切换的全流程,并总结了SPIFFS操作、WebSocket通信等核心优化点。该方案无需专用APP,适合物联网设备快速部署场景

u011697185的专栏 960

Spark算子--map和mapPartition的区别,配实例讲解

map和mapParttion都是spark的算子,他们在进行数据处理时有一定的区别: map是RDD中的每一个元素进行操作。 mapPartition是对RDD的每一个分区的迭代器进行操作,返回的是迭代器。 mapPartiton的优势: 提高性能,比如我们对一个含有100条log数据的分区进行操作,使用map的话函数要执行100次计算。使用MapPartitions操作之后,一个task...

SOARING 1万+

Calpuff模型实战:从气象数据预处理到污染物扩散模拟全流程指南

本文提供了一份详尽的Calpuff模型实战指南,涵盖从气象数据预处理、地形处理到污染物扩散模拟与结果可视化的全流程。重点解析了Calmet气象场构建、Calpuff核心参数配置,并与AERMOD模型进行对比,帮助环境工程师与科研人员掌握这一强大的三维非稳态拉格朗日扩散模型,以应对复杂地形、海岸熏烟等实际模拟挑战。

s4t5u6v7的博客 459

2.4G/4G天线共存方案:Air8101多频段隔离设计实战(附波长计算表)

本文深入探讨了物联网设备中Wi-Fi 2.4GHz与4G LTE天线共存设计的实战方案。针对B40与2.4G频段紧邻带来的干扰挑战,文章系统性地提出了空间隔离、PCB布局优化、结构设计三重防线,并提供了关键的波长计算工具与系统级验证Checklist,旨在帮助工程师将多频段隔离设计从“玄学”变为可执行的工程规范。

weixin_29197051的博客 389

spark RDD算子(十二)之RDD 分区操作上mapPartitions, mapPartitionsWithIndex

一、mapPartitions mapPartition可以倒过来理解。先partition,再把每个partition进行map函数 适用场景: 如果再映射的过程中需要频繁创建额外的对象,使用mapPartitions要比map高效的多 比如,将RDD中的所有数据通过JDBC连接写入数据库,如果使用map函数,可能要为每一个元素都创建一个connection,这样开销很大,如果使用mapPartitions,那么只需要针对每一个分区建立一个connection。 案例:把每一个元素平方 Java版本 pu

qianchun22的博客 661

U2Net网络实战:从原理到代码实现(附背景去除应用)

本文深入解析了U2Net网络的原理与代码实现,重点剖析了其独特的嵌套U型结构(RSU模块)和显著图融合机制。通过实战演示,指导读者如何加载预训练模型并应用于精准的图像背景去除任务,为电商、摄影等领域提供高效的自动化抠图解决方案。

nn3456的博客 491

Spark RDD算子(十一) RDD 分区操作 mapPartitions、mapPartitionsWithIndex、glom

一、mapPartitions mapPartition可以倒过来理解,先partition,再把每个partition进行map函数 适用场景 如果在映射的过程中需要频繁创建额外的对象,使用mapPartitions要比map高效。 比如,将RDD中的所有数据通过JDBC连接写入数据库,如果使用map函数,可能要为每一个元素都创建一个connection,这样开销很大,如果使用mapPartitions,那么只需要针对每一个分区建立一个connection。 下面的例子 java实现,把每一个元素平方 S

timicai的博客 378

uniapp [全端兼容] - 详细实现人脸识别和活体检测功能,实时监测人脸是否进入区域及动作是否正确播报,免费自动提示引导动作及语音,提供提供实名认证、身份证识别、人脸信息采集、刷脸扫脸认证示例代码

uniapp,h5移动端网页,微信小程序,支付宝小程序,Android安卓,苹果ios,app,nvue,人脸识别,扫脸认证,人脸认证,活体认证,身份认证,uni-app人脸识别详细教程,如何在app端实现免费人脸识别教程,如何在小程序端做,最好用的插件,安卓ios百度人脸识别、活体检测、人脸采集APP,H5人脸识别带前后摄像头,适合新手看的人脸识别功能教程,详细示例代码源码,有没有免费的,接入百度,阿里云人脸识别,百度,api,活体检测,数据采集,动作提示指引,语音提示指引,报错,无法核验一直出错,根本用

🏆 前端领域优质创作者 1万+

第一章:信号链的精度之战:深入解决电流采样偏差

摘要:本文深入探讨了FOC控制中电流采样偏差问题及其解决方案。电流采样偏差主要来源于偏移误差、增益误差、非线性误差和温漂四大类,其中偏移误差对FOC性能影响最为严重。硬件方面建议采用高精度采样电阻、低失调运放和独立基准电压等设计;软件层面提出了上电自动零点校准、在线实时补偿和模型闭环补偿三种策略。最后介绍了量产自动化校准系统,通过硬件优化和软件补偿相结合,确保每台产品电流采样精度的一致性,为FOC控制奠定坚实基础。

汽车软件开发 602

大数据——Spark RDD算子(十二)RDD分区操作mapPartitions、mapPartitionsWithIndex

Spark RDD算子(十二)RDD分区操作mapPartitions、mapPartitionsWithIndexmapPartitions把每一个元素变成map(i,i*i)Scala版本Java版本把(i,j) 变成(i,j*j)Scala版本Java版本把每一个元素平方Java版本mapPartitionsWithIndex统计各个分区中的元素Scala版本Java版本 mapPartitions mapPartitions可以倒过来理解,先partition,再把每个partition进行map

蜂蜜柚子加苦茶 646

matlab电子科技大学数学实验期末模拟35道(1)

【代码】matlab电子科技大学数学实验期末模拟35道。

c_wrj_的博客 2044

Spark RDD算子:分区操作,mapPartitions和mapPartitionsWIthIndex

mapPartitions mapPartitions的执行过程是先进行分区,然后对分区内的元素进行相应的操作。如果在映射的过程中需要频繁的创建额外的对象,使用mapPartitions比map要更加高效。 举一些例子:计算每个元素乘以2. Java端 package Action; import org.apache.spark.SparkConf; import org.apache.spark.api.java.JavaPairRDD; import org.apache.spark.api.jav

qq_43012693的博客 979

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Spark RDD算子之RDD 分区操作 -- mapPartitions、mapPartitionsWithIndex、glom

1、mapPartitions 先 partition,再把每个 partition 进行 map 函数 适用场景 如果在映射的过程中需要频繁创建额外的对象,使用mapPartitions要比map高效的多。 比如,将RDD中的所有数据通过JDBC连接写入数据库,如果使用map函数,可能要为每一个元素都创建一个connection,这样开销很大,如果使用mapPartitions,那么只需要针对每一个分区建立一个connection。 把 RDD 中每一个元素平方! Java版本 SparkConf con

绿萝蔓蔓绕枝生 629

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

Spark RDD算子只分区操作mapPartitions、mapPartitionsWithIndex(scala和java版本)

mapPartitions 可以理解为先进行partition,再对每一个partition进行map 1、把每一个元素 i 变为 map(i , i*i) scala版本 val rdd = sc.parallelize(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)) def mapPartFunc(iter: Iterator[Int]): Iterator[(Int, Int)] = { val res = List[(Int, Int)]()

xiaoxionghanhan的博客 563

spark labeledpoint函数用法_Spark性能优化:基于分区进行操作

我的原创地址:Spark性能优化:基于分区进行操作​dongkelun.com前言(摘自Spark快速大数据分析)基于分区对数据进行操作可以让我们避免为每个数据元素进行重复的配置工作。诸如打开数据库连接或创建随机数生成器等操作,都是我们应当尽量避免为每个元素都配置一次的工作。Spark 提供基于分区的map 和foreach,让你的部分代码只对RDD 的每个分区运行一次,这样可以帮助降低这些操作的...

weixin_39636718的博客 378

Spark核心编程3-map,mapPartitions,flatMap,glom,分区,groupby

一、算子介绍(RDD方法既称为算子) RDD方法分为转换和行动两个内容。 转换:功能的补充,也就是复杂业务逻辑,生产多个RDD的过程,旧的RDD包装成新的RDD,相互包装补充; 行动:触发任务调度和作业的执行。封装并不会触发任务的执行,如flatmap,map等,只有collect等才能触发。 二、转换算子(RDD方法) 根据数据类型不同可以把算法分为三大类型单value ,双value,key-value; 2.1 map map函数式将处理的数据逐条进行映射转换,可以是值或者类型的转换。.

Icedeny的博客 723

spark map和mapPartitions区别

主要区别: map是对rdd中的每一个元素进行操作; mapPartitions则是对rdd中的每个分区的迭代器进行操作 MapPartitions的优点: 如果是普通的map,比如一个partition中有1万条数据。ok,那么你的function要执行和计算1万次。 使用MapPartitions操作之后,一个task仅仅会执行一次function,function一次接收所有...

weixin_36058293的博客 307

Spark部分:按照分区插入数据(map,mappartitions和foreachPartition)【Java版全代码】

package com.bjsxt.spark; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import org.apache.spark.api.java.function.Function; import org.apache...

wyqwilliam的博客 3197

spark中分区算子

功能:对RDD每个分区的数据进行操作,将每个分区的数据进行map转换,将转换的结果放入新的RDD中。

qq_58242165的博客 267

Spark使用mapPartitions获取分区下的元素

mapPartitions解析 底层源码 /** * Return a new RDD by applying a function to each partition of this RDD. * * `preservesPartitioning` indicates whether the input function preserves the partitioner,...

Jamie's Blogs 714

RDD转换操作算子 --- map类

转换操作RDD算子 map 将RDD一对一的转化为另一种形式 @Test def map(): Unit ={ //val source: Seq[Int] = Seq(1,2,3,4,5,6) val source: RDD[Int] = sc.parallelize(Seq(1,2,3,4,5,6)) val map: Array[Int] = source.map(item => item*10) .collect() map.forea

懂得一千零一种,赋予你失败的方法! 1488

2.3.1.2 Value类型-mapPartitions()以分区为单位执行Map

2.3.1.2 Value类型-mapPartitions()以分区为单位执行Map ----------------转载放原连接,违权必究-------------------------- 1、格式: mapPartitions(f : Iterator[T]=> Iterator[U],pP:Boolean = false) : RDD[U] 2、功能: 1、原来RDD中的元素按照一个分区为一个Iterator,遍历分区 2、每个分区数据(Iterator)依次按批次进入mapPartitio

qq_41549462的博客 237
上一篇: 动手实现第一个Hadoop程序的扩展
下一篇: 一个简单的UDF小程序(HIVE)
ITrue的天空
博客等级 码龄14年 4粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值