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

从零开始:kohya_ss环境部署与LoRA/SDXL模型训练实战指南

本文提供了一份详细的kohya_ss环境部署与模型训练实战指南。从零开始,手把手教你使用Conda创建虚拟环境、安装依赖并启动Web GUI界面。核心内容涵盖高质量数据集的准备方法,并重点解析了如何使用kohya_ss工具进行LoRA模型和SDXL模型的微调训练,包括关键参数配置与常见报错解决方案,帮助初学者快速上手AI绘画模型定制。

weixin_29162439的博客 536

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

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

SOARING 1万+

别急着编译!修复银河麒麟OpenSSH漏洞前,先搞懂ssh、sshd版本与apt仓库的“爱恨情仇”

本文深度解析银河麒麟OpenSSH漏洞(CVE-2023-38408)修复策略,揭示版本差异背后的企业级维护逻辑,提供从APT升级到源码编译的多维度方案评估。特别针对路径隔离方案和离线环境处理给出技术细节,帮助企业制定兼顾安全与稳定的升级决策框架。

weixin_26642481的博客 454

NVIDIA显卡驱动历史版本全攻略:从官网隐藏入口到精准下载

本文详细介绍了如何获取NVIDIA显卡驱动历史版本的完整攻略,包括官网隐藏入口的揭秘、精准筛选驱动版本的技巧以及安装避坑指南。特别针对游戏玩家、创作者和老显卡用户提供了实用建议,帮助用户解决驱动兼容性问题,提升显卡性能。

m2n3o4p5的博客 3733

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

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

qianchun22的博客 661

使用kmplot在线进行生存分析

欢迎关注”生信修炼手册”!kmplot是一个生存分析的在线工具,最初是设计用来对肝癌中的miRNA进行生存分析,对应的文章发表在scientific reports上,链接如下https...

庐州月光的博客 1万+

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

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

timicai的博客 378

避坑指南:Qt5.14.2 ARM交叉编译中那些你可能遇到的‘坑’及解决方案

本文深度解析了Qt 5.14.2在ARM架构上进行交叉编译的完整流程与常见难题。重点阐述了如何精准匹配交叉编译器与目标板环境、正确配置sysroot以及使用configure参数的艺术,并针对编译过程中的头文件缺失、链接错误等典型“坑”提供了经过验证的解决方案,旨在帮助开发者成功构建适用于嵌入式设备的Qt运行时库。

weixin_29279101的博客 354

禅道二次开发(一):从零搭建本地开发与调试环境

本文详细介绍了禅道二次开发的第一步:从零搭建本地开发与调试环境。通过部署官方一键安装包、配置端口与防火墙、连接数据库、设置Samba文件共享,并最终在VSCode中配置PHP智能感知与Xdebug调试,手把手教你建立一个隔离、高效的专属开发工作台,为后续的代码修改与功能扩展奠定坚实基础。

weixin_29003437的博客 323

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

游戏引擎揭秘:大厂为何死磕自研?

游戏引擎本质与商业价值解析 游戏引擎是集成了渲染、物理、动画等核心功能的开发工具包,其价值在于让开发者免于重复编写底层代码,专注于游戏内容创作。商业引擎(如Unity/Unreal)虽降低了开发门槛,但头部厂商仍坚持自研引擎,主要基于以下考量: 经济性:长期项目分摊自研成本后,比商业引擎分成更划算; 可控性:完全掌握底层代码,能针对性优化核心玩法需求; 技术壁垒:专属引擎成为厂商的竞争优势,如米哈游的跨平台渲染技术; 项目适配:超大型游戏(开放世界/MMO)需要深度定制解决方案。 这种"短期高投入

本博客聚焦游戏开发技巧、创业实战心得及大学热门课程干货。这里既有技术深度,也有思维广度,无论你是开发者、创业者还是高校学子,都能在这里找到适合自己的成长之路! 263

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

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

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

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

绿萝蔓蔓绕枝生 629

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

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

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

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

余额充值