Spark RDD

概念

RDD是一种抽象,是Spark对于分布式数据集的抽象,它用于囊括所有内存中和磁盘中的分布式数据实体

RDD 与 数组对比

对比项 数组 RDD
概念类型 数据结构实体 数据模型抽象
数据跨度 单机进程内 跨进程、跨计算节点
数据构成 数组元素 数据分片(Partitions)
数据定位 数组下标、索引 数据分片索引

RDD 4大属性

partitions 数据分片: 数据属性

partitioner 分片切割规则: 定义了把原始数据集切割成数据分片的切割规则

dependencies RDD依赖: 每个RDD都会通过dependencies属性来记录它所依赖的前一个、或是多个RDD,简称"父RDD"

compute 转换函数: 与此同时,RDD使用compute属性,来记录从父RDD到当前RDD的转换操作

例子

不同的食材形态,如带泥土豆、土豆片、即食薯片等等,对应的就是RDD概念

同一种食材形态在不同流水线上的具体实物,就是 RDD 的 partitions 属性

食材按照什么规则被分配到哪条流水线,对应的就是 RDD 的 partitioner 属性

每一种食材形态都会依赖上一种形态,这种依赖关系对应的是 RDD 中的 dependencies 属性

不同环节的加工方法对应 RDD的 compute 属性

RDD 编程模型

在RDD的编程模型中,一共有两种算子,Transformations 类算子和Actions类算子

开发者需要使用Transformations 类算子,定义并描述数据形态的转换过程,然后调用Actions类算子,将计算结果收集起来、或是物化到磁盘

延迟计算

RDD编程模型下,Spark在运行时的计算被划分为两个环节

  • 基于不同数据形态之间的转换,构建计算流图(DAG,Directed Acyclic Graph)
  • 通过Actions类算子,以回溯的方式去触发执行这个计算流图

换句话说,开发者调用的各类Transformations算子,并不立即执行计算

当且仅当开发者调用Actions算子时,之前调用的转换算子才会付诸执行

常用算子

算子类型 适用范围 算子用途 算子集合
Transformations 任意RDD RDD内数据转换 map、mapPartitons、mapPartitonsWithIndex、flatMap、 filter
Paired RDD RDD内数据耦合 groupByKey、sortByKey、reduceByKey、aggregateByKey
任意RDD RDD间数据整合 union、intersection、join、cogroup、cartesian
任意RDD 数据整理 sample、distinct
Actions 任意RDD 数据收集 collect、first、take、takeSample、takeOrdered、count
任意RDD 数据持久化 saveAsTextFile、saveAsSequenceFile、saveAsObjectFile
任意RDD 数据遍历 foreach

map: 元素为粒度对RDD做数据转换

复制代码
val rdd: RDD[Int] = sc.parallelize(Seq(1, 2, 3, 4, 5))
val result: RDD[Int] = rdd.map(x => x + 1)
result.collect() // 返回 Array(2, 3, 4, 5, 6)

在这个例子中,我们使用 parallelize 方法创建一个包含整数的 RDD
接着,我们使用 map 算子将 RDD 中的每个整数都加上 1,生成一个新的 RDD
最后,我们使用 collect 方法将新的 RDD 中的元素取回到驱动程序中

mapPartitons: 以数据分区为粒度,使用映射函数f对RDD进行数据转换

复制代码
val rdd = sc.parallelize(List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), 3)
val result = rdd.mapPartitions(partition => {
  val sum = partition.sum
  Iterator(sum)
}).collect()

这个例子中,我们首先创建了一个包含10个元素的RDD,并将其分成3个分区
然后,我们使用mapPartitions算子,以数据分区为粒度进行转换
在这个例子中,我们使用partition.sum计算每个数据分区的和,并将其放入一个新的迭代器中
最后,我们使用collect算子将结果收集到本地
这个例子展示了如何使用mapPartitions算子以数据分区为单位进行操作,从而提高执行效率

flatMap:从元素到集合、再从集合到元素

复制代码
val sentences: RDD[String] = sc.parallelize(List("Hello world", "How are you", "I am fine"))
val words: RDD[String] = sentences.flatMap(sentence => sentence.split(" "))

在上面的代码中,我们首先创建了一个包含多个句子的 RDD,然后使用 flatMap 方法,对每个句子进行拆分操作
具体地,对于 RDD 中的每个元素(即句子),我们都将其分割成单词,然后使用 yield 关键字将每个单词作为一个新的元素返回
最终,我们得到了一个包含所有单词的 RDD

filter:过滤RDD

复制代码
val numbersRDD = sc.parallelize(Seq(-2, 0, 5, -10, 7, -3, 9))
val positiveNumbersRDD = numbersRDD.filter(x => x >= 0)
positiveNumbersRDD.foreach(println) // RDD[0, 5, 7, 9]

我们创建了一个包含数字的RDD,然后使用filter算子过滤掉其中的负数,最终返回一个新的RDD,只包含正数

mapPartitionsWithIndex: 每个元素映射为一个包含索引和单词的元组

复制代码
val data = List("apple", "banana", "orange", "grape", "pear")
val rdd = sc.parallelize(data, 2)

val result = rdd.mapPartitionsWithIndex { (index, partition) =>
  partition.map(word => (index, word))
}

result.foreach(println)

这段代码创建了一个包含 5 个元素的列表,并将其转换为一个包含 2 个分区的 RDD
接着,使用 mapPartitionsWithIndex 函数将每个元素映射为一个包含索引和单词的元组,最后打印出结果

在这个例子中,mapPartitionsWithIndex 函数的输入函数接受两个参数:分区索引和分区中的元素迭代器
元素迭代器包含了分区中的所有元素,因此我们可以在其中使用 map 函数对所有元素进行操作
最终的输出结果是一个包含索引和单词的元组的 RDD

groupByKey:分组收集

groupByKey的字面意思是"按照Key做分组",但实际上,groupByKey算子包含两步,即分组和收集

相关推荐
张张123y1 小时前
后端第十四课:Agent 记忆系统(让 Agent 记住上下文和用户,跨会话不健忘)
java·大数据·人工智能·python·agent·记忆
找方案7 小时前
从用户画像到智能定价:81页方案拆解“大数据决策与支撑平台”怎么落地
大数据·人工智能·数据分析·智慧城市·用户画像
liliangcsdn7 小时前
DeepSeek DeepInfer开源项目的功能分析和探索
大数据·人工智能
xiaogai_gai8 小时前
钉钉月结报销到金蝶付款单同步方案实战教程
大数据·数据库·钉钉
Elastic 中国社区官方博客9 小时前
Elasticsearch:安装自行管理的 Elastic Stack 集群
大数据·运维·服务器·数据库·elasticsearch·搜索引擎·全文检索
商业看点解说10 小时前
支持私有化部署的 AI 助手有哪些?把“私有化“拆成四层,排除一类常被错放的产品
大数据·人工智能
清华kenny10 小时前
安徽晓得养HIS系统适合哪类健康机构升级使用
大数据·人工智能·安徽晓得养
SelectDB11 小时前
数仓 TCO 怎么算:五项成本拆解框架速查
大数据·数据库·开源
戴西软件11 小时前
制造研发中的AI视觉与仿真:戴西工程图纸智能审图智能体、戴西3DViz_CAE AI集成与戴西3DViz_CAD AI集成
大数据·运维·人工智能·3d·自动化·制造·rpa