一、创建
1.外部数据源
(1)读取win读取win (读取多个文件)
val conf=new SparkConf().setAppName("New Test").setMaster("local")
val sc=new SparkContext(conf)
val readText=sc.textFile("D:\\example\\1.txt,D:\\example\\2.txt")
val result=readText.saveAsTextFile("D:\\all\\result")
(2)加载HDFS保存Linux (含通配符的路径)
val conf=new SparkConf().setAppName("wordcount")
val sc=new SparkContext(conf)
val input=sc.textFile("hdfs://master:9000/hive/*.txt")
val lines=input.flatMap(line=>line.split(" "))
val count=lines.map(word=>(word,1)).reduceByKey{case (x,y)=>x+y}
val output=count.saveAsTextFile("file:///data1/test/result")
(3)加载HDFS保存HDFS
val conf=new SparkConf().setAppName("cal_wel")
val sc=new SparkContext(conf)
val rdd=sc.textFile("hdfs://master:9000/hive/order_20200105.txt");
val rdd1=rdd.map(line=>(line.split("\t")(1),1)).reduceByKey((x,y)=>x+y)
rdd1.repartition(1).saveAsTextFile("hdfs://master:9000/tmp/result")
二、算子
1.Transformation
map(func) | 返回一个新RDD。该RDD由每一个输入元素经过func函数转换后组成 |
filter(func) | 返回一个新RDD。该RDD由经过func函数计算后返回值为true的输入元素组成 |
flatMap(func) | 类似map,但每一个输入元素可以被映射为0或多个输出元素 |
distinct([numTasks]) | 对源RDD进行去重后返回一个新RDD |
union(otherDataset) | 对源RDD和参数RDD求并集后返回一个新RDD |
join(otherDataset,[numTasks]) | 在类型为(K,V)和(K,W)的RDD上调用,返回一个相同key对应的所有元素对在一起的(K,(V,W))的RDD,相当于内连接 |
leftOuterJoin | 类上,左连接 |
rightOuterJoin | 类上,右连接 |
groupByKey([numTasks]) | 在一个(K,V)的RDD上调用,返回一个(K,Iterator[V])的RDD |
reduceByKey(func,[numTasks]) | 在一个(K,V)的RDD上调用,返回一个(K,V)的RDD,使用指定迭代reduce函数,将相同key的值聚合到一起,与groupBy类似。reduce任务的个数可以通过第2个可选参数来设置 |
sortByKey([ascending],[numTasks]) | 在一个(K,V)的RDD上,K必须实现Ordered接口,返回一个按照key进行排序的(K,V)的RDD |
combineByKey | 合并相同的key值,将RDD[K,V]转化为RDD[K,C] |
mapValues(func) | 在一个(K,V)的RDD上,key不变,对每个value都应用func函数 |
persist | RDD缓存,可避免重复计算从而减少时间,可选择缓存级别 |
cache | RDD缓存,可避免重复计算从而减少时间,cache内部调用了persist算子,cache摩恩只有一个缓存级别MEMORY-ONLY |
sample(withReplacement,fraction,seed) | 根据fraction指定的比例对数据进行采样,可以选择是否使用随机数进行替换,seed用于指定随机数生成器种子 |
coalesce(numPartitions,shuffle) | 重新分区。第1个参数分为多少区,第2个参数是否shuffle |
repartition(numPartitions) | 重新分区,调用coalesce且第2个参数为true的实现 |
2.Action
collect | 返回RDD中的所有元素 | rdd.collect() |
foreach(func) | 对RDD中的每个元素使用给定的函数 | rdd.foreach(func) |
count | RDD中的元素个数 | rdd.count() |
reduce(func) | 并行整合RDD中所有元素 | rdd.reduce((x,y)=>x+y) |
take(num) | 从RDD中返回前num个元素 | rdd.take(2) |
takeSample(withReplacement, num, [seed]) | 从RDD返回任意一些元素 | rdd.takeSample(false, 1) |
top(num) | 从RDD中返回最前面的num个元素 | rdd.top(2) |
countByValue | 各元素在RDD中出现的次数 | rdd.countByValue() |
takeOrdered(num) | 从RDD中按照提供的顺序返回最前面的num个元素 | rdd.takeOrdered(2) |
fold(0)(func) | 和reduce一样,但需要提供初始值 | rdd.fold(0)((x,y)=> x+y) |
aggregate(zeroValue)(seqOp, combOp) | 类似reduce,但通常返回不同类型函数 | rdd.aggregate((0,0))( (x,y)=>(x._1+y,x._2+1), (x,y)=>(x._1+y._1,x._2+y._2)) |
first | 返回第1个元素 | rdd.first() |
sum | 总和 | rdd.sum() |
三、应用
1.map
对RDD中的每个元素都执行一个指定的函数来产生一个新的RDD。
返回值:RDD
- 示例
def map1(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(1,2,3,4))
val rdd1=rdd.map(line=>line+1)
rdd1.foreach(println)
}
def map2(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(("spark",0),("hadoop",10),("hadoop",4),("spark",4)))
val mapRdd=rdd.map(line=>(line,1))
mapRdd.foreach(println)
}
def map3(sc:SparkContext):Unit={
val rdd=sc.textFile("E:\\data\\spark\\rdd\\test\\read\\movies.csv")
val arr=rdd.map(line=>line.split(",")).collect()
for(i <- 0 to 2){
for(j <- 0 to 2){
print(arr(i)(j)+"\t")
}
println()
}
}
2.filter
对RDD元素进行过滤,返回一个新的数据集。(经过func函数后返回值为true的原元素组成)
返回值:RDD
- 示例
def filter1(sc:SparkContext):Unit={
val rdd=sc.textFile("E:\\data\\spark\\rdd\\test\\read\\movies.csv")
val filterRdd=rdd.filter(line=>line.contains("Drama"))
filterRdd.foreach(println)
}
def filter2(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(1,2,3,7,4,5,8))
val filterRdd=rdd.filter(x=>x>=4)
filterRdd.foreach(println)
}
3.flatMap
类似map,但对每一个输入元素,会被映射为0到多个输出元素
而mapPartitions的输入函数是每个分区的数据,也就是把每个 分区的内容作为整体来处理的。
- 示例
def flatMap1(sc:SparkContext):Unit={
val rdd=sc.parallelize(1 to 10,3)
rdd.foreach(println)
}
def flatMap2(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(("A",1),("B",2),("C",3)))
rdd.flatMap(x=>(x._1+x._2)).foreach(println)
}
4.mapPartitions
mapPartitions是map的一个变种。可看作先对RDD进行partition,再把每个partition进行map函数。
map的输入函数是应用于RDD中每个元素,而mapPartitions的输入函数是每个分区的数据。
即把每个分区中的内容作为整体来处理的
- 应用场景
当数据量不太大的时候,可以用mapPartitions,可以提高运行效率;
当数据量太大的时候,有可能会发生oom
- 示例
def mapPartitions1(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(1,2,3,4,5,6), 2)
val mapPartitionsRdd=rdd.mapPartitions(_.map(_+1))
mapPartitionsRdd.foreach(println)
}
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
}
def mapPartitions2(sc:SparkContext):Unit={
val rdd=sc.parallelize(1 to 9, 3)
val mapPartitionsRdd=rdd.mapPartitions(doubleFunc)
println(mapPartitionsRdd.collect().mkString)
}
def menaFunc(iter:Iterator[Int]):Iterator[(Int,Int)]={
var x,y=0
var res=List[(Int,Int)]()
while(iter.hasNext){
val cur=iter.next
x+=cur
y+=1
}
res.::=(x,y)
res.iterator
}
def reduceFunc(x:(Int,Int),y:(Int,Int)):(Int,Int)={
(x._1+y._1, x._2+y._2)
}
def mapPartitions3(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(1,2,3,4),3)
val sum=rdd.mapPartitions(menaFunc).reduce(reduceFunc)
println(sum._1/sum._2.asInstanceOf[Float])
}
5.mapPartitionsWithIndex
mapPartitionsWithSplit与mapPartitions的功能类似,只是多传入split index而已。
所有func函数必须是(Int,Iterator<T>)=>Iterator<U>类型
- 示例
def func(index:Int, it:Iterator[Int]):Iterator[String]={
it.map(x=>s"part:$index, ele:$x")
}
def mapPartitionsWithIndex1(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(1,2,3,4,5,6),2)
val mapPartitionsWithIndexRdd=rdd.mapPartitionsWithIndex(func)
mapPartitionsWithIndexRdd.foreach(println)
}
def mapPartitionsWithIndex2(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array("tom1","tom2","tom3","tom4","tom5","tom6"),3)
val mapPartitionsWithIndexRdd=rdd.mapPartitionsWithIndex((index,x)=>{
val list=ListBuffer[String]()
while(x.hasNext){
list+="part:"+index+", ele:"+x.next
}
list.iterator
})
mapPartitionsWithIndexRdd.foreach(println)
}
6.sample
sample (withReplacement,fraction,seed)是根据给定的随机种子seed,随机抽样出数量为frac的数据。
withReplacement:是否放回抽样
fraction:比例。比如0.1表示10%
seed:随机种子
返回值:RDD
- 示例
def sample1(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(2,3,7,4,8))
val sampleRdd=rdd.sample(false,0.5)
sampleRdd.foreach(println)
}
def sample2(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(2,3,7,4,8))
val sampleRdd=rdd.sample(true,2)
sampleRdd.foreach(println)
}
def sample3(sc:SparkContext):Unit={
val rdd=sc.makeRDD(List(1,2,3,7,4,5,8))
val sampleRdd=rdd.sample(false,0.25,System.currentTimeMillis())
sampleRdd.foreach(println)
}
7.union
union(otherDataset)是数据合并,返回一个新的数据集,又原数据集和otherDataset联合而成。
返回值:RDD
- 示例
def union1(sc:SparkContext):Unit={
val rdd1=sc.makeRDD(List("张三","李四"))
val rdd2=sc.makeRDD(List("tom","marry"))
val unionRdd=rdd1.union(rdd2)
unionRdd.foreach(println)
}
8.intersection
intersection(otherDataset)是数据交集,返回一个新的数据集。(两个数据集的交集数据)。
返回值:RDD
- 示例
def intersection1(sc:SparkContext):Unit={
val rdd1=sc.makeRDD(List("张三","李四","王五","tom"))
val rdd2=sc.makeRDD(List("tom","lilei"))
val intersectionRdd=rdd1.intersection(rdd2)
intersectionRdd.foreach(println)
}
9.distinct
distinct([numTasks])是数据去重,返回一个数据集,是对连个数据集去除重复数据
numTasks是设置任务并行数量
- 示例
def distinct1(sc:SparkContext):Unit={
val rdd=sc.parallelize(List("张三","李四","王五","李四","王五"))
val distinctRdd=rdd.distinct()
distinctRdd.foreach(println)
}
10.groupByKey
groupByKey([numTasks])是数据分组操作,在一个由(K,V)对组成的数据集上调用,返回一个(K,Seq[V])对的数据集。
返回值:RDD[ Tuple2[K,Iterable[V]] ]
- 示例
def groupByKey1(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array("one","two","three","three","three","one"))
val mapRdd=rdd.map(line=>(line,1))
val groupByKeyRdd=mapRdd.groupByKey()
groupByKeyRdd.foreach(println)
}
def groupByKey2(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(("A",0),("A",2),("B",1),("B",8),("C",3)))
val groupByKeyRdd=rdd.groupByKey()
groupByKeyRdd.foreach(println)
}
11.reduceByKey
reduceByKey(func,[numTasks])是一个(K,V)对的数据集上使用,返回一个(K,V)的数据集。
key相同的值,都被使用指定的reduce函数聚合到一起。
返回值:RDD[ Tuple2[K, V] ]
- 示例
def reduceByKey1(sc:SparkContext):Unit={
val rdd=sc.makeRDD(Array(("A",0),("A",2),("B",3),("B",4),("C",6)))
val reduceByKeyRdd=rdd.reduceByKey((x,y)=>x+y)
reduceByKeyRdd.foreach(println)
}
def reduceByKey2(sc:SparkContext):Unit={
val rdd=sc.textFile(Constant.LoCAL_FILE_PREX+"/data/rdd/wordData.log")
println(Constant.LoCAL_FILE_PREX)
val reduceByKeyRdd=rdd.flatMap(line=>line.split("\\s+")).map(x=>(x,1)).reduceByKey((x,y)=>x+y)
reduceByKeyRdd.foreach(println)
}
12.aggreateByKey
aggreateByKey和reduceByKey的不同之处在于,reduceByKey输入输出都是(K,V),而aggreateByKey输出是(K,U)
aggreateByKey的3个参数:
zeroValue:U,初始值,比如空列表{}
seqOp:(U,T)=>U,seq操作符,描述如何将T合并如U,比如如何将item合并到列表
combOp:(U,T)=>U,comb操作符,描述如何合并两个U,比如合并两个列表
所以aggreateByKey可以看成更高抽象的,更灵活的reduce或group
- 示例
def aggregateByKey1(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(("cat",3), ("cat", 1), ("mouse", 4), ("dog", 9), ("mouse", 2)),2)
val aggregateByKeyRdd=rdd.aggregateByKey(100)(_+_, _+_)
aggregateByKeyRdd.foreach(println)
}
def combOp(a:List[Int], b:List[Int]):List[Int]={
a.:::(b)
}
def seqOp(a:List[Int], b:Int):List[Int]={
a.::(b)
}
def aggregateByKey2(sc:SparkContext):Unit={
val rdd=sc.parallelize(List((1,3),(1,2),(1,4),(2,3)))
val aggregateByKeyRdd=rdd.aggregateByKey(List[Int]())(seqOp,combOp)
aggregateByKeyRdd.foreach(println)
}
13.combineByKey
对RDD中的数据集按照Key进行聚合操作,聚合操作的逻辑是通过自定义函数提供给combineByKey。
- 参数
combineByKey[C](createCombiner: (V) ⇒ C, mergeValue: (C, V) ⇒ C, mergeCombiners: (C, C) ⇒ C, numPartitions: Int):RDD[(K, C)]
(1) combinByKey会遍历rdd中每一个(k,v)数据对,对该数据对中的k进行判断,判断该(k,v)对中的k是否在之前出现过,如果是第一次出现,则调用createCombiner函数,对该k对应的v进行初始化操作
(2)作用在每一个分区内部,将V合并到之前(createCombiner)的元素上
(3)当所有的分区内的数据计算完成之后,开始调用mergeCombiners函数,对每个分区的数据进行合并
- 示例
def combineByKey1(sc:SparkContext):Unit={
val rdd=sc.makeRDD(Array(("A",1),("A",2),("B",3),("B",4),("C",6)))
val combineByKeyRdd=rdd.combineByKey((v:Int)=>v+"-",(c:String,v:Int)=>c+"@"+v,(c1:String,c2:String)=>c1+"$"+c2)
combineByKeyRdd.foreach(println)
}
def combineByKey2(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array((1, 1.0), (1, 2.0), (1, 3.0), (2, 4.0), (2, 5.0), (2, 6.0)))
val combineByKeyRdd=rdd.combineByKey((v:Double)=>(v,1), (c:(Double,Int),v:Double)=>(c._1+v,c._2+1),(c1:(Double,Int),c2:(Double,Int))=>(c1._1+c2._1, c1._2+c2._2))
combineByKeyRdd.foreach(println)
}
def combineByKey3(sc:SparkContext):Unit={
val rdd=sc.parallelize(List(("A", 3), ("A", 9), ("A", 12),("B", 4), ("B", 10), ("B", 11)), 2)
val combineByKeyRdd=rdd.combineByKey(
(x:Int)=>(x,1),
(acc:(Int,Int), x)=>(acc._1+x, acc._2+1),
(p1:(Int,Int), p2:(Int,Int))=> (p1._1+p2._1, p1._2+p2._2)
)
combineByKeyRdd.foreach(println)
}
def combineByKey4(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(("coffee",1), ("coffee",2), ("panda",3), ("coffee",9)))
val combineByKeyRdd=rdd.combineByKey(score=>(1,score), (c:(Int,Int),newScore:Int)=>(c._1+1,c._2+newScore), (c1:(Int,Int),c2:(Int,Int))=>(c1._1+c2._1,c1._2+c2._2))
val averageRdd=combineByKeyRdd.map{
//case(key,value)=>(key,value._2/value._1)
case(name,(num,score))=>(name,score/num)
}
averageRdd.foreach(println)
}
def combineByKey5(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array((("1","011"),1), (("1","012"),1), (("2","011"),1), (("2","013"),1), (("2","014"),1)))
val combineByKeyRdd=rdd.map(x=>(x._1._1, (x._1._2,1))).combineByKey(
(v:(String,Int))=> (v:(String,Int)),
(acc:(String,Int), v:(String,Int))=> (acc._1+":"+v._1, acc._2+v._2),
(p1:(String,Int), p2:(String,Int))=> (p1._1+":"+p2._1, p1._2+p2._2)
)
combineByKeyRdd.foreach(println)
}
14.sortByKey
sortByKey([ascending],[numTasks])是排序操作,对(K,V)类型的数据按照K进行排序,其中K需要实现Ordered方法
返回值:RDD[ Tuple2[K, V] ]
- 示例
def sortByKey1(sc:SparkContext):Unit={
val rdd=sc.makeRDD(List((60,"张三"), (70,"李四"), (80,"王五"), (55,"赵六"), (45,"郭七"), (75,"林八")))
val sortByKeyRdd=rdd.sortByKey()
sortByKeyRdd.foreach(println)
}
def sortByKey2(sc:SparkContext):Unit={
val rdd=sc.makeRDD(List((60,"张三"), (70,"李四"), (80,"王五"), (55,"赵六"), (45,"郭七"), (75,"林八")))
val sortByKeyRdd=rdd.sortByKey(false) //降序
sortByKeyRdd.foreach(println)
}
15.join
join(otherDataset,[numTasks])是连接操作,讲那个输入数据集(K,V)和另外一个(K,W)进行join,得到(K,(V,W)
该操作是对于相同K的V和W集合进行笛卡尔积操作,即V和W的所有组合
连接操作除了join外,还有左连接leftOuterJoin、右连接rightOuterJoin、全连接fullOuterJoin
- 示例
def join1(sc:SparkContext):Unit={
val productRdd=sc.parallelize(List((1,"苹果"),(2,"梨"),(3,"香蕉"),(4,"石榴")))
val countRdd=sc.parallelize(List((1,7),(2,3),(3,8),(4,3),(5,9)))
val joinRdd=productRdd.join(countRdd)
joinRdd.foreach(println)
}
def leftOuterJoin1(sc:SparkContext):Unit={
val productRdd=sc.parallelize(List((1,"苹果"),(2,"梨"),(3,"香蕉"),(4,"石榴")))
val countRdd=sc.parallelize(List((1,7),(2,3),(3,8),(4,3),(5,9)))
val joinRdd=productRdd.leftOuterJoin(countRdd)
joinRdd.foreach(println)
}
def rightOuterJoin1(sc:SparkContext):Unit={
val productRdd=sc.parallelize(List((1,"苹果"),(2,"梨"),(3,"香蕉"),(4,"石榴")))
val countRdd=sc.parallelize(List((1,7),(2,3),(3,8),(4,3),(5,9)))
val joinRdd=productRdd.rightOuterJoin(countRdd)
joinRdd.foreach(println)
}
16.cogroup
cogroup(otherDataset,[numTasks])是将输入数据集(K,V)和另外一个数据集(K,W)进行congroup,得到一个格式为(K,Seq[V],Seq[V])的数据集。
返回值:RDD[ Tuple2[K, Tuple2[ Iterable[V], Iterable[W] ] ] ]
- 示例
def cogroup1(sc:SparkContext):Unit={
val rdd1=sc.parallelize(Array((1,"a"),(2,"b"),(3,"c"),(4,"d")))
val rdd2=sc.parallelize(Array((1,4),(2,5),(3,6)))
val cogroupRdd=rdd1.cogroup(rdd2)
cogroupRdd.foreach(println)
}
17.cartesian
cartesian(otherDataset)是做笛卡尔积:对于数据集T和U进行笛卡尔积操作,得到(T,U)格式的数据集
返回值:RDD[ Tuple2[T, U] ]
- 示例
def cartesian1(sc:SparkContext):Unit={
val rdd1=sc.parallelize(1 to 3)
val rdd2=sc.parallelize(4 to 6)
val cartesianRdd=rdd1.cartesian(rdd2)
cartesianRdd.foreach(println)
}
18.coalesce
将RDD进行重分区
- 示例
/*
def coalesce(numPartitions: Int, shuffle: Boolean = false)(implicit ord: Ordering[T] = null): RDD[T]
参数1:重分区数目
参数2: 是否进行shuffle,默认false
功能:将RDD进行重分区,使用HashPartitioner
*/
def coalesce1(sc:SparkContext):Unit={
val rdd=sc.textFile("E:\\data\\spark\\rdd\\test\\read\\ml-25m\\genome-scores.csv")
println("分区数:"+rdd.partitions.size) //13
val coalesceRdd=rdd.coalesce(2)//减少分区数
println("新分区数:"+coalesceRdd.partitions.size) //2
coalesceRdd.saveAsTextFile("E:\\data\\spark\\rdd\\test\\write\\ml-25m")//2
}
def coalesce2(sc:SparkContext):Unit={
val rdd=sc.textFile("E:\\data\\spark\\rdd\\test\\read\\ml-25m\\genome-scores.csv")
println("分区数:"+rdd.partitions.size) //13
val coalesceRdd=rdd.coalesce(20,true)//将shuffle设为true,增加分区数到200
println("新分区数:"+coalesceRdd.partitions.size) //20
coalesceRdd.saveAsTextFile("E:\\data\\spark\\rdd\\test\\write\\ml-25m")//20
}
19.repartition
将RDD进行重分区,即coalesce函数第2个参数为true的实现
- 示例
def repartition1(sc:SparkContext):Unit={
val rdd=sc.textFile("E:\\data\\spark\\rdd\\test\\read\\ml-25m\\genome-scores.csv")
println(rdd.getNumPartitions)
rdd.repartition(1).saveAsTextFile("E:\\data\\spark\\rdd\\test\\read\\ml-25m\\genome-scores")
}
20.persist
将RDD进行缓存(持久化),可避免重复计算从而减少时间
- 源码
def persist(newLevel: StorageLevel): this.type = {
if (storageLevel != StorageLevel.NONE && newLevel != storageLevel) {
throw new UnsupportedOperationException(
"Cannot change storage level of an RDD after it was already assigned a level")
}
sc.persistRDD(this)
sc.cleaner.foreach(_.registerRDDForCleanup(this))
storageLevel = newLevel
this
}
- 缓存级别
参数1:useDisk 使用硬盘
参数2:useMemory 使用内存
参数3:useOffHeap使用堆外内存
参数4:反序列化
参数5:备份数
object StorageLevel {
val NONE = new StorageLevel(false, false, false, false)
val DISK_ONLY = new StorageLevel(true, false, false, false)
val DISK_ONLY_2 = new StorageLevel(true, false, false, false, 2)
val MEMORY_ONLY = new StorageLevel(false, true, false, true)
val MEMORY_ONLY_2 = new StorageLevel(false, true, false, true, 2)
val MEMORY_ONLY_SER = new StorageLevel(false, true, false, false)
val MEMORY_ONLY_SER_2 = new StorageLevel(false, true, false, false, 2)
val MEMORY_AND_DISK = new StorageLevel(true, true, false, true)
val MEMORY_AND_DISK_2 = new StorageLevel(true, true, false, true, 2)
val MEMORY_AND_DISK_SER = new StorageLevel(true, true, false, false)
val MEMORY_AND_DISK_SER_2 = new StorageLevel(true, true, false, false, 2)
val OFF_HEAP = new StorageLevel(false, false, true, false)
......
}
示例:
val MEMORY_AND_DISK_SER_2=new StorageLevel(true,true,false,false,2)
使用该缓存级别的RDD将存储在硬盘以及内存中,使用序列化(在硬盘中),并且在多个节点上备份2份(正常的RDD只有1份)
- 示例
def persist1(sc:SparkContext):Unit={
val rdd=sc.textFile("E:\\data\\spark\\rdd\\test\\read\\ml-25m\\genome-scores.csv")
rdd.persist(StorageLevel.MEMORY_AND_DISK)
val count1=rdd.count
println("count1:"+count1) //耗时10636
val count2=rdd.count
println("count2:"+count2) //耗时279
val count3=rdd.count
println("count3:"+count3) //耗时264
}
21.cache
将RDD进行缓存(持久化)。内部调用persist,只有一个默认缓存级别MEMORY_ONLY
- 示例
def cache1(sc:SparkContext):Unit={
val rdd=sc.textFile("E:\\data\\spark\\rdd\\test\\read\\ml-25m\\genome-scores.csv")
rdd.cache()
val count1=rdd.count
println("count1:"+count1) //耗时10575
val count2=rdd.count
println("count2:"+count2) //耗时411
val count3=rdd.count
println("count3:"+count3) //耗时273
}
三、Action操作
1.reduce
reduce(func)是对数据集的所有元素执行聚集func函数,该函数必须是可交换的
将RDD中元素两两传递给输入函数,同时产生一个新值,新值与RDD中下一个元素再被传递给输入函数直到最后一个值为止
返回值:T
- 示例
def reduce1(sc:SparkContext):Unit={
val rdd=sc.makeRDD(List("a","ab","abc","abcd","abcde"))
val reduceNum=rdd.map(x=>x.length).reduce((x,y)=>x+y)
println(reduceNum)
}
def reduce2(sc:SparkContext):Unit={
val rdd=sc.textFile("E:\\data\\spark\\rdd\\test\\read\\app1.log")
val reduceNum=rdd.map(line=>line.split(" ").size).reduce((a,b)=> if(a>b) a else b)
println(reduceNum)
}
2.collect
将一个RDD转换为数组
返回值:Array[T]
- 示例
def collect1(sc:SparkContext):Unit={
val rdd=sc.makeRDD(1 to 5,4)
val collectArr=rdd.collect
for(i <- collectArr)
println(i)
}
3.count
返回数据集中元素的个数
返回值:Long
- 示例
def count1(sc:SparkContext):Unit={
val rdd=sc.parallelize(1 to 5)
println(rdd.count())
}
def count2(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(("A","1"),("B",2),("C",3)))
val countNum=rdd.count
println(countNum)
}
4.first
返回数据集中的第一个元素,类似take(1)
返回值:T
- 示例
def first1(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(5,4,8,3,0))
println(rdd.first())
}
def first2(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array("a","ab","abc","abcd"))
val firstMap=rdd.map(line=>(line,line.length)).first
println(firstMap)
}
5.take
返回一个包含数据集中前n个元素的数组,当前该操作不能并行
返回值:Array[T]
- 示例
def take1(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(4,8,3,0,1,9))
val takeRdd=rdd.take(2)
takeRdd.foreach(println)
}
def take2(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array("a","ab","abc","abcd"))
val takeRdd=rdd.map(line=>(line,line.length)).take(3)
takeRdd.foreach(println)
}
6.takeOrdered
takeOrdered(n,[ordering])将RDD中的每个元素进行升序排序后取topN
返回值:Array[T]
- 示例
def takeOrderedTest(sc:SparkContext):Unit={
val rdd=sc.makeRDD(Seq(10,4,2,12,3,1))
val takeOrderedRdd=rdd.takeOrdered(2)
takeOrderedRdd.foreach(println)
}
7.top
将RDD中的每个元素进行降序排序后取topN
def top(num: Int)(implicit ord: Ordering[T]): Array[T] = withScope {
takeOrdered(num)(ord.reverse)
}
- 示例
def top1(sc:SparkContext):Unit={
val rdd=sc.makeRDD(Seq(10,4,2,12,3,1))
val topRdd=rdd.top(2)
topRdd.foreach(println)
}
8.takeSample
takeSample(withReplacement,num,[seed])返回包含随机的num个元素的数组
和Sample不同,takeSample是Action操作,因此返回的是数组而不是RDD
withReplacement:是否有抽样放回
num:抽取多少个
返回值:Array[T]
- 示例
def takeSample1(sc:SparkContext):Unit={
val rdd=sc.makeRDD(1 to 10)
val sampleRdd=rdd.takeSample(true,4) //有放回抽样,采取数量4
sampleRdd.foreach(println)
}
9.saveAsTextFile
把数据集中的元素写到一个文本文件,Spark会对每个元素调用toString()方法把每个元素存成文本文件的一行
- 示例
def saveAsTextFile1(sc:SparkContext):Unit={
val rdd=sc.makeRDD(Seq(("A",1),("B",2),("C",3),("D",4),("E",5),("F",6)),4)
rdd.saveAsTextFile("E:\\data\\spark\\rdd\\test\\write\\saveAsTextFile")
}
10.countByKey
对于(K,V)类型的RDD,返回一个(K,Int)的map,Int为K的个数
- 示例
def countByKey2(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(("A","1"),("B",2),("C",3),("A",5)))
val countByKeyRdd=rdd.countByKey
countByKeyRdd.foreach(println)
}
11.foreach
foreach(func)是对数据集中的每个元素都执行func函数
- 示例
def foreach1(sc:SparkContext):Unit={
val rdd=sc.parallelize(Array(("A","1"),("B",2),("C",3),("A",5)))
rdd.foreach(println)
}