-
RDD的使用
-
1什么是RDD
-
RDD的全称为Resilient Distributed Dataset,是一个弹性、可复原的分布式数据集,是Spark中最基本的抽象,是一个不可变的、有多个分区的、可以并行计算的集合。RDD中并不装真正要计算的数据,而装的是描述信息,描述以后从哪里读取数据,调用了用什么方法,传入了什么函数,以及依赖关系等。
1.2RDD的特点
- 有一些列连续的分区:分区编号从0开始,分区的数量决定了对应阶段Task的并行度
- 有一个函数作用在每个输入切片上: 每一个分区都会生成一个Task,对该分区的数据进行计算,整函数就是具体的计算逻辑
- RDD和RDD之间存在一些列依赖关系:RDD调用Transformation后会生成一个新的RDD,子RDD会记录父RDD的依赖关 系,包括宽依赖(有shuffle)和窄依赖(没有shuffle)
- (可选的)K-V的RDD在Shuffle会有分区器,默认使用HashPartitioner
- (可选的)如果从HDFS中读取数据,会有一个最优位置:spark在调度任务之前会读取NameNode的元数据信息,获取数据的位置,移动计算而不是移动数据,这样可以提高计算效率。
1.3RDD的算子分类
1.Transformation:即转换算子,调用转换算子会生成一个新的RDD,Transformation是Lazy的,不会触发job执行。
2. Action:行动算子,调用行动算子会触发job执行,本质上是调用了sc.runJob方法,该方法从最后一个RDD,根据其依赖关系,从后往前,划分Stage,生成TaskSet。
1.3.1创建RDD的方法
- 通过并行化方式,将Driver端的集合转成RDD
|
2.从HDFS指定的目录据创建RDD
|
注意,使用上面两种方式创建RDD都可以指定分区的数量
1.3.2查看RDD的数量
|
1.3.3RDD常用的Transformation算子
1.map算子,功能所做映射
|
2.flatMap算子,先map在压平,spark中没有flatten方法
|
3.filter算子,功能为过滤数据
|
4.mapPartitions,将数据以分区为的形式返回进行map操作,一个分区对应一个迭代器,该方法和map方法类似,只不过该方法的参数由RDD中的每一个元素变成了RDD中每一个分区的迭代器,如果在映射的过程中需要频繁创建额外的对象,使用mapPartitions要比map高效的过。
val rdd1 = sc.parallelize(List(1, 2, 3, 4, 5),2)
val r1: RDD[Int] =rdd1.map(x=>x)
var r2: RDD[Int] = rdd1.mapPartitions(it => it.map(x => x * 10))
5.mapPartitionsWithIndex,类似于mapPartitions, 不过函数要输入两个参数,第一个参数为分区的索引,第二个是对应分区的迭代器。函数的返回的是一个经过该函数转换的迭代器。
val conf = new SparkConf().setAppName("TransformationDemo")
val sc: SparkContext = new SparkContext(conf)
val arr: RDD[Int] = sc.parallelize(Array(3, 7, 5, 8, 2, 3, 7, 4, 5),2)
arr.mapPartitionsWithIndex((in