一、創建
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)
}