文章目录
1 RDD
1.1 RDD分类和算子的基本概念
- 什么是算子:RDD处理数据的方法。
- 为什么要叫做算子: 为了和scala集合方法区分 因为scala集合方法在Driver端执行 而RDD的方法可在不同的Executor端执行

1.2 转换算子–value型
-
map
- 文本数据逐行转换 内存数据逐个转换
- 分区内:一条数据执行完所有算子的逻辑后 下一条数据才开始执行
- 分区间:并发执行 互不影响
-
mapParatition
- 和map算子很像,区别在于map是一条一条执行 而该算子是以整个分区数据 为基本执行单位,在整个分区内做一些操作(整个分区的数据最为迭代器,因此可以调用一些迭代器的一些操作 最大值 最小值 )。如果分区数据未处理完 所有分区数据都不会释放 内存大推荐使用性能高 否则内存容易溢出。
/**
* 四个区
* 第一个分区 5/4=1 arr[0]=2
* 第二个分区 5*2/4 arr[1]=4
* 第三个分区 arr[2]=1
* 第四个分区 4*5/4=5 arr[3]=3
* arr[4]=5
*/
val rdd = sparkContext.makeRDD(List(2,4,1,3,5),4)
val value = rdd.mapPartitions(iter => {
// TODO iter表示每个分区的数据 可以调用迭代器的方法 例如最小最大值 过滤等
println(iter.max)
iter
})
println(value.collect().mkString("\n"))
- mapPartitionsWithIndex:一个分区一个分区执行 分区内做一些操作,操作的同时获取分区号
// 分区号和 index 表示分区号 iter 表示分区的数据
val value = rdd.mapPartitionsWithIndex((index, iter) => {
List((index, iter.max)).iterator
})
- flatMap(fun):将集合中的元素打散成单独元素 每个元素执行fun函数。将所有的返回结果返回到一个集合中,返回结果的集合元素是一个一个基本类型 不能再是集合类型。
- map和flaymap的区别见以下例子
- map函数后,RDD的值为 Array(Array(“a”,“b”),Array(“c”,“d”),Array(“e”,“f”))
- flatMap函数处理后,RDD的值为 Array(“a”,“b”,“c”,“d”,“e”,“f”)。即最终可以认为,flatMap会将其返回的数组全部拆散,然后合成到一个数组中
object MapAndFlatMap {
def main(args: Array[String]): Unit = {
val sc = new SparkContext(new SparkConf().setAppName("map_flatMap_demo").setMaster("local"))
val arrayRDD =sc.parallelize(Array("a_b","c_d","e_f"))
/**
* a_b
* c_d
* e_f
*/
arrayRDD.foreach(println) //打印结果1
arrayRDD.map(string=>{
string.split("_")
}).foreach(x=>{
/**
* a,b
* c,d
* e,f
*/
println(x.mkString(",")) //打印结果2
})
arrayRDD.flatMap(string=>{
string.split("_")
}).foreach(x=>{
/**
* a,b,c,d,e,f
*
*/
println(x.mkString(","))//打印结果3
})
}
}
-
glom() :将分区数据转为数组

-
filter:将数据根据指定的规则进行筛选过滤,符合规则的数据保留,不符合规则的数据丢弃。
-
groupBy :将数据根据指定的规则进行分组, 分区默认不变,但是数据会被打乱重新组合,我们将这样的操作称之为shuffle。极限情况下,数据可能被分在同一个分区中
/**
* 根据单词的首写字母进行分组
*
*/
object RDD_GroupBy {
def main (args: Array[String] ): Unit = {
val sparkContext = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("RDD_GroupBy"))
val rdd1 = sparkContext.makeRDD(List("Hello", "hive", "hbase", "Hadoop"),3)
val rdd2 = rdd1.groupBy(x => {
// 或者x(0)
val str = x.toString.substring(0, 1)
if ("H".equals(str)) {
0
} else if ("h".equals(str)) {
1
}
})
println(rdd2.collect().mkString(","))
}
}
- sample:抽取数据 从数据倾斜的数据分区中抽取数据 看看是不是相同的数据太多了 后续再优化处理
/**
* 随机数抽取
* 参数1:是否放回
* 参数2:被抽中的概率 2:表示被抽中的两次 至于一定能被抽中两次不一定 这只是表示概率
* 参数3:随机数种子,随机算法都要一个初始值,如果没有一个初始值,
* 他也不能凭空制造一系列的随机数出来,那我们说的随机种子seed()就是这是初始值。
* 默认初始值是系统时间
*/
object RDD_Smaple {
def main(args: Array[String]): Unit = {
val sparkContext = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("flatmap"))
val value1 = sparkContext.makeRDD(List(1, 2, 3, 4, 5, 7, 8), 1)
println(value1.sample(true, 2, 3).collect().mkString(","))
}
}
- distinct 数据去重 去重通过方法参数改变分区数量 因为去重后数据量变少
/**
* 随机数抽取
*/
object RDD_Distinct {
def main(args: Array[String]): Unit = {
val sparkContext = new SparkContext(new SparkConf().setMaster("local[*]").setAppName("flatmap"))
val value1 = sparkContext
.makeRDD(List(1, 2, 1, 2, 3, 4, 3,4), 2)
// 去重后改变分区
.distinct(1)
println(value1.collect().mkString(","))
val value2 = sparkContext
// 去重不改变分区
.makeRDD(List(1, 2, 1, 2, 3, 4, 3,4), 2).distinct()
println(value2.collect().mkString(","))
}
}
- coalesce:根据数据量缩减分区,用于大数据集过滤后,提高小数据集的执行效率.shuffer默认是false 不打乱数据重组。
- repartition
- 该操作内部其实执行的是coalesce操作,参数shuffle的默认值为true。无论是将分区数多的RDD转换为分区数少的RDD,还是将分区数少的RDD转换为分区数多的RDD,repartition操作都可以完成,因为无论如何都会经shuffle过程。
- sortBy
def sortBy[K](
f: (T) => K,
ascending: Boolean = true,
numPartitions: Int = this.partitions.length)
- 该操作用于排序数据。在排序之前,可以将数据通过f函数进行处理,之后按照f函数处理的结果进行排序,默认为正序排列。排序后新产生的RDD的分区数与原RDD的分区数一致。
val dataRDD = sparkContext.makeRDD(List(1,2,3,4,1,2),2)
val dataRDD1 = dataRDD.sortBy(num=>num, false, 4)
1.3 RDD算子–双value型 两个RDD value型数据做操作
- 交集 并集 差集 拉链
object RDD_OPOperator {
def main (args: Array[String])

这篇博客详细介绍了Spark中的RDD算子,包括转换算子如map、filter、groupBy等,以及双value型操作和kv类型数据操作。同时,文章还讨论了行动算子如reduce、collect、count等功能,并解释了算子间的关系,如血缘关系和依赖关系,以及RDD的持久化机制如Cache和CheckPoint。
最低0.47元/天 解锁文章
664

被折叠的 条评论
为什么被折叠?



