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

ZYNQ裸机LWIP双网口实现

文章目录前言一、LWIP双网口二、使用步骤1.部分说明2.部分代码总结 前言 一、LWIP双网口 由于项目需要多通讯口,查阅资料发现lwip支持多网口操作。于是,就开搞了。 二、使用步骤 1.部分说明 利用xemac_add函数在网卡链表中添加一个网卡,即使用netif块重复xemac_add操作。 先用轮询的方式实现双网口,后期修改为中断模式 2.部分代码 导入官方例程LWip echo server, 修改main函数,增加一个netif块 #if LWIP_IPV6==0 #if L..

weixin_35865280的博客 1万+

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

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

SOARING 1万+

手把手教你解决Kernel panic报错:init找不到的5种排查方法(附NFS挂载实战)

本文深入解析了Linux系统启动时出现“Kernel panic - not syncing: No working init found”报错的根本原因,并提供了五种系统性的排查方法。文章结合NFS挂载根文件系统的实战场景,详细阐述了从动态链接库依赖、内核引导参数、NFS权限配置、文件系统完整性到内核配置干扰的完整排查路径,帮助开发者快速定位并解决这一常见的系统启动故障。

weixin_29159995的博客 196

GB28181协议实战:5分钟搞定海康摄像头SIP注册失败问题(附Wireshark抓包分析)

本文详细解析了海康摄像头在GB28181协议下SIP注册失败的7个关键原因及解决方案,包括网络可达性、鉴权参数、NAT穿越等核心问题。通过Wireshark抓包分析,提供快速定位方法,帮助工程师高效解决SIP注册失败问题,提升实时图像联调效率。

weixin_29212867的博客 556

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

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

qianchun22的博客 661

IROS 2025机器人技术解析:从诡异设计到硬核应用

机器人技术正从传统的结构化环境应用,迈向复杂非结构化场景的深度交互。其核心原理在于通过仿生设计、多模态感知与智能控制算法,赋予机器人类似生物的适应性与交互能力。这一技术演进的价值在于突破传统机器人在极端环境、精密操作和自然交互中的瓶颈。例如,结合深度强化学习的全身动力学控制,使机器人能在废墟、管道等复杂地形中自主导航;而软体机器人技术则通过材料变形实现安全、柔顺的抓取操作。这些技术最终服务于极端环境巡检、精密装配和高端陪护等刚性应用场景,推动机器人从功能实现迈向与环境、人进行深度、智能交互的新阶段。

weixin_34006468的博客 450

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

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

timicai的博客 378

告别CPU空转!用STC8的SPI+DMA高效驱动上百颗WS2812B灯珠

本文详细解析了如何利用STC8单片机的SPI+DMA外设高效驱动WS2812B全彩灯珠,解决传统软件延时驱动方式在长灯带应用中的性能瓶颈。通过硬件方案设计、数据格式转换和DMA传输配置,实现高达400Hz的刷新率和低于5%的CPU占用率,适用于大规模灯光项目。

weixin_30847939的博客 397

5步搞定ABB机器人RobotStudio与S7-1500PLC的Profinet通讯(附PLCSIM调试技巧)

本文详细介绍了如何利用RobotStudio与TIA Portal软件,结合PLCSIM Advanced仿真器,在零硬件条件下实现ABB机器人与西门子S7-1500 PLC之间的Profinet通讯虚拟调试。通过五个核心步骤,从环境搭建、网络配置、信号映射到联合仿真与高级调试,帮助工程师在项目前期高效验证逻辑、压缩现场调试周期,并掌握实用的PLCSIM调试技巧。

weixin_29188043的博客 505

大数据——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

传感器使用——ESP-WROOM-32 and INMP441麦克风音频采集

传感器使用——ESP-WROOM-32 and INMP441麦克风音频采集,数据显示及matlab操作界面。

qq_41958946的博客 7355

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

【AUTOSAR-E2E】-2.2-配置E2E:基于E2EPW配置一个TX发送的Signal Group(使用E2E Profile 2)

《共13页精讲》:此法也适用于E2E Profile 4/5/6/7/11/22 目录 1 检查CAN Matrix Arxml/DBC是否满足E2E需求 2 在DaVinci Developer中为Port添加E2E保护 3 在DaVinci Configurator settings设置 4 如何使用应用层的E2E保护 5 结尾 <--返回「Autosar_BSW高阶配置」总目录--> <--返回「Autosar_BSW高阶配置」专栏主页--> &lt.

「汽车电子助手」的博客 4219

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

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

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

绿萝蔓蔓绕枝生 629

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

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

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

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、付费专栏及课程。

余额充值