RDD方法:1.转换:功能的补充和封装,将旧的RDD包装成新的RDD(flatmap,map)
2.行动:触发任务的调度和作业的执行(collect)
IDEA代码自动补全https://cloud.tencent.com/developer/article/1581092
scala匿名函数需要学习一下,类似过程:
//val mapRDD: RDD[Int] = rdd.map(mapFunction)
//val mapRDD: RDD[Int] = rdd.map((num:Int)=>{num*2})
//val mapRDD: RDD[Int] = rdd.map((num:Int)=>num*2)
//val mapRDD: RDD[Int] = rdd.map((num:Int)=>num*2)
//val mapRDD: RDD[Int] = rdd.map((num)=>num*2)
//val mapRDD: RDD[Int] = rdd.map(num=>num*2)
val mapRDD: RDD[Int] = rdd.map(_*2)
RDD方法=>RDD算子(operator)
RDD转换算子:根据数据处理方式不同整体分为1.Value类型 2.双Value类型3.Key-Value类型
Value类型
1.map:将处理的数据逐(zhu)条进行映射转换,可以是类型,也可以是值的转换。
小功能:从服务器日志数据apache.log中获取用户请求URL资源路径(今天6.9记得回去下载学习资料放进U盘里)
//读取log文件,文件行数据类型为ip地址 - - path
//只选择path信息
//TODO 算子-map
val rdd=sc.textFile("data/apache.log")
//长字符串=>短字符串
val mapRDD: RDD[String] = rdd.map(
line => {
val datas = line.split(" ")
datas(6)
}
)
mapRDD.collect().foreach(println)
rdd的计算一个分区内的数据是一个个执行逻辑,只有前面一个数据全部逻辑执行完毕后才会执行下一个数据。分区内数据的执行是有序的。不同分区数据计算是无序的。
以上方法类似于java IO流的单字节操作,引入新的算子,类比成buffer提供缓冲区。
rdd.mapPartitions()迭代器返回迭代器,批处理的感觉。
2.mapPartitions:将待处理的数据以分区为单位发送到计算结点进行处理,这里的处理是指可以进行任意的处理,如过滤数据
可以以分区为单位进行数据转换操作,但是会将整个分区的数据加载到内存进行引用。如果处理完的数据是不会被释放,存在对象的引用。在内存较小,数据量较大的场合下,容易出现内存溢出。
取获取分区数据最大值作为一个小功能进行实现 45节
//TODO 算子-mapPartition
val rdd=sc.makeRDD(List(1,2,3,4),2)
val mpRDD: RDD[Int] = rdd.mapPartitions(
iter => {
List(iter.max).iterator
//iter.map(_ * 2)
}
)
mpRDD.collect().foreach(println)
map和mapPartitions区别
1.数据处理角度
map:分区内一个数据一个数据的执行,类似于串行操作。
mapPartitions:以分区为单位进行批处理操作
2.功能角度
map:将数据源中数据进行转换和改变,但不会减少或增多数据
mapPartitions:需传递一个迭代器并返回一个迭代器。没有要求元素个数保持不变,所以可以增加或减少数据
3.性能角度
map:类似于串行操作,所以性能较低
mapPartitions:类似于批处理,性能较高但是会长时间占用内容,导致内存不够用,内存溢出的错误。
内存有限使用map
3.mapPartitionsWithIndex:将待处理数据以分区为单位发送到计算节点进行处理,做任何处理,在处理同时获取当前分区索引。
f:(Int, Iterator[T])=>Iteator[U]
小功能:获取第二个数据分区的数据
val rdd=sc.makeRDD(List(1,2,3,4),2)
val mpiRDD=rdd.mapPartitionsWithIndex(
(index,iter)=>{
if(index==1){
iter
}else{
Nil.iterator
}
//iter
})
mpiRDD.collect().foreach(println)
获取数据分区的索引
val rdd = sc.makeRDD(List(1, 2, 3, 4))
val mpiRDD=rdd.mapPartitionsWithIndex(
(index,iter)=>{
//(0,1)(2,2)
iter.map(
num=>{
(index,num)
}
)
}
)
mpiRDD.collect().foreach(println)
4.flatMap:将处理的数据进行扁平化处理后再进行映射处理,算子也称为扁平映射(48节)
小功能:将List(List(1,2),List(4,5))进行扁平化操作
//TODO 算子-flatmap
val rdd: RDD[List[Int]] = sc.makeRDD(List(
List(1, 2), List(3, 4)
))
val flatRDD: RDD[Int] = rdd.flatMap(
list => {
list
}
)
flatRDD.collect().foreach(println)
现在遇到一个大问题,scala下的split无法使用。pom.xml被我改坏了。
重新开始建立scala项目,添加pom.xml中的依赖关系。加入log4配置文件(第10节)。
https://www.cnblogs.com/-beyond/p/11557196.html
IDEA存在缓存,所以pom文件修改后读取的是缓存中pom的为了提高效率,但是type mismatch问题并没有解决
https://www.cnblogs.com/yanch01/p/12258713.html
https://www.cnblogs.com/jooy/p/9146527.html
index过程缓慢,暂时没有解决。
5.glom:将同一个分区的数据直接转换为相同类型的内存数组进行处理,分区不变。数据也没有发生变化。
计算所有分区最大值求和(分区内取最大值,分区内最大值求和)分区内写逻辑
6.groupBy
分组和分区没有必然联系。有底层逻辑但是没有必然关系。
分组可能会导致数据分区不一样。group会把数据打乱,重新组合,这个操作叫shuffle。极限情况下,数据可能被分在同一分组。
7.filter
最后通过改版本暂时解决spark-core_2.12 version 2.4.3
之前3.0.0一些函数不支持,错误的修改了pom文件。引入的包造成冲突后,又去program structure进行problem fix。被直接remove了。还没解决为什么。mark一下之后过来改。