Spark常用算子

RDD:

  1. 分区列表
  2. 作用在分区上的函数
  3. 依赖列表
  4. (可选)对于PairRDD,持有一个分区器
  5. (可选)优先适用的数据分片存储位置列表

获取RDD=======================================================================
来自外部文件
val rdd0=sc.textFile("/hadoop/profile")
来自集合
val rdd1=sc.parallelize(List(1,2,3,4,5,6),2)   指定该rdd有两个分区
获取rdd分区的集合及分区数
rdd1.partitions.length
val rdd2=sc.parallelize(List(2,3,2,5))
val rdd3=sc.parallelize(List(("a",1),("b",1),("a",2),("c",3))
a 1
b 1
a 2
c 3
val rdd4=sc.parallelize(List(("a","m"),("b","f"),("d",1)))
a m
b f
d 1
val rdd5=sc.parallelize(List(("a",1),("b",3),("a",2),("b",5)))
a 1
b 3
a 2
b 5
val rdd6=sc.parallelize(List("a","b","c","d"))


转换===========================================================================
持久化到内存,注意持久化本身也是延迟加载的,cache与persist相同,但后者可以设置其他级别
rdd1.cache()  rdd1.persist()
取消持久化rdd1.unpersist(true)
设置检查点文件夹
sc.setCheckpointDir("hdfs://ns1/hadoop")
为rdd设置检查点,存放于之前设置的检查点文件夹中(必须先设置该文件夹),也是延迟的,只有遇到action才会执行
设置检查点之后遇到action,spark将会为checkpoint和action分别启动一个任务计算数据,如果先将rdd做cache处理再checkpoint,则可以不必重新计算,检查点和后面的action都可以使用持久化的数据

  • sc.setCheckpointDir("hdfs://ns1/hadoop")
  • rdd1.cache()
  • rdd1.checkpoint
  • rdd1.count

去重rdd2.distinct
筛选rdd1.filter(_<3)
排序rdd1.sortBy(_%3)
合并rdd1.union(rdd2)
交集rdd1.intersection(rdd2)
笛卡尔积rdd2.cartesian(rdd4)
缝合rdd6.zip(rdd2)  两个RDD分别作为key、value组合成pairRDD (a,2) (b,3) (c,2) (d,5)
重新分区rdd1.repartition(2)
筛选
rdd5.filter(_._1=="b")   对RDD的元素进行筛选(pairRDD视为tuple的RDD)
rdd3.filterByRange("b","c") 对pairRDD的key按上下限进行范围筛选

RDD->pairRDD
rdd2.keyBy(_.toString+"a")  将每个值处理后作为key,原值作为value组成pairRDD
(2,3,2,5)->((2a,2),(3a,3),(2a,2),(5a,5))
pairRDD->RDD
rdd3.keys
rdd3.values

flatMap
("abc","def","gh")->("a","b","c","d","e","f","g","h")
flatMapValues
rdd.flatMapValues((x:Int)=>(""+x).split("")).collect
("a",123),("b",56)->(a,1), (a,2), (a,3), (b,5), (b,6)

关联
rdd3.join(rdd4)    innerjoin
rdd3.fullOuterJoin(rdd4)
rdd3.leftOuterJoin(rdd4)
rdd3.rightOuterJoin(rdd4)
分组
rdd3.groupByKey()    (a,(1,2)) (b,1) (c,3) -> (key,Iterable(values))
聚合
rdd3.groupByKey().mapValues(_.sum)   (key,Iterable(values)) -> (key,valuesum)
分组聚合(比groupByKey多了一个本地combine的过程,效率更高)
rdd3.reduceByKey(_+_)

cogroup相当于rdd3做groupByKey,rdd5做groupByKey,再关联起来
rdd3.cogroup(rdd5)
得到(key, (Iterable[values1], Iterable[values2]))
(c,(CompactBuffer(3),CompactBuffer())), (a,(CompactBuffer(2, 1),CompactBuffer(1, 2))), (b,(CompactBuffer(1),CompactBuffer(5, 3)))

针对每个分区执行map,用于本地combine,提高效率
rdd1.mapPartitions(x=>x.take(2))    Iterator[T]->Iterator[U]

rdd2.mapPartitions(x => x.toList.sortBy(-_).take(3).iterator).collect
rdd1.mapPartitionsWithIndex((x,y)=>y.toList.map((x,_)).iterator) (Int x,Iterator[T] y)->Iterator[U]

分区聚合
rdd1内容为(1,2,3    ,4,5,6)
rdd1.aggregate(5)(_+_,_+_)
第一个参数为初始值,第二个参数为两个函数,func1为(U,T)->U,func2为(U,U)->U(初始值与累计结果类型为U)
执行步骤为对于每个分区,取值T与初始值U累计合并,函数为func1
5+1+2+3=11,5+4+5+6=20
对每个分区,将结果U与初始值U累计合并,函数为func2,注意此时各分区的汇总值进行累计的顺序是随机的,即"start"+"b"+"c"或者"start"+"c"+"b"
5+11+20=36

分区分组聚合aggregateByKey
val pairRDD = sc.parallelize(List( ("cat",2), ("cat", 5), ("mouse", 4)    ,("cat", 12), ("dog", 12), ("mouse", 2)), 2)
查看分区情况
def func2(index: Int, iter: Iterator[(String, Int)]) : Iterator[String] = {
  iter.toList.map(x => "[partID:" +  index + ", val: " + x + "]").iterator
}
pairRDD.mapPartitionsWithIndex(func2).collect  等于  pairRDD.mapPartitionsWithIndex((x,y)=>y.toList.map((x,_)).iterator).collect
(0,(cat,2)), (0,(cat,5)), (0,(mouse,4)), (1,(cat,12)), (1,(dog,12)), (1,(mouse,2))
pairRDD.aggregateByKey(5)(math.max(_, _), _ + _).collect  传入初始值和func1/func2,都是(U,U)->U
相当于对于每个分区执行一次groupByKey,得到List((key,Iterator(value))),
(cat,(2,5))  (mouse (4))    |(cat, (12)), (dog, (12)), (mouse, (2))
对每个Iterator(value)使用初始值进行func1累计,注意此处使用了初始值
(cat,5)      (mouse,5)      |(cat, 12), (dog, 12), (mouse, 5)
将各分区的结果合并,再执行groupByKey
(cat,(5,12)) (mouse,(5,5)) (dog,(12))
再对每个Iterator(value)进行func2累计,注意此处不使用初始值
(cat,17)  (mouse,10)  (dog,12)

分组聚合reduceByKey
reduceByKey是aggregateByKey的特例,即func1与func2相等,同时由于aggregateByKey先基于分区聚合,所以reduceByKey也自带分区combine,效率高于groupByKey

分组聚合最初始形态combinByKey
combineByKey(T=>U,(U,T)=>U,(U,U)=>U)
相当于aggregateByKey(startvalue)((U,T)=>U,(U,U)=>U),但是每个分区的初始值由分区第一个元素经过T=>U转化得到,注意func2是(U,T)而不是(T,U),即前面为累计值,后面为新进值
pairRDD.combineByKey(x=>math.max(x,5),(x:Int,y:Int)=>math.max(x,y), (x:Int,y:Int)=>x+y).collect
等价于
pairRDD.aggregateByKey(5)(math.max(_, _), _ + _).collect
注意func2,func3中必须指明参数类型(即上式中的Int)
e.g.
val rdd9 = sc.parallelize(List("dog","cat","gnu","salmon","rabbit","turkey","wolf","bear","bee"), 3)
val rdd10 = sc.parallelize(List(1,1,2,2,2,1,2,2,2), 3)
val rdd11 = rdd5.zip(rdd4)
(1,dog), (1,cat), (2,gnu), (2,salmon), (2,rabbit), (1,turkey), (2,wolf), (2,bear), (2,bee)
rdd11.combineByKey(List(_),(x:List[String],y:String)=>x:+y,(x:List[String],y:List[String])=>x++y).collect
((1,List(turkey, dog, cat)), (2,List(salmon, rabbit, gnu, wolf, bear, bee)))

action================================================================================
以下结果都不需要collect
rdd1.reduce(_+_)
rdd1.collect
rdd5.collectAsMap 将pairRDD收集为map,注意由于map的性质,key重复的pair只保留一个
rdd1.reduce  (T,T)->T 注意聚合前后类型必须相同,因为reduce相当于aggregate的func1与func2相同,而func2要求更严格(前后一致)
rdd1.count
rdd5.countByKey 仅对pairRDD有效,根据key分组计数
rdd2.countByValue 根据RDD的元素分组计数,返回一个Map(对于pairRDD,会将每个tuple当做一个整体的元素)
rdd1.top(2) 取最大的前几个
rdd1.take(2) 取自然顺序的前几个
rdd1.first = rdd1.take(1)
对每个分区执行操作(注意不返回结果)
rdd.foreachPartition(x=>println(x.reduce(_+_)))
对每个值执行操作(注意不返回结果)
rdd.foreach(println(_))
排序后取前几名
rdd1.takeOrdered(5)(Ordering[Int].on(_%3))
等于先排序再take
rdd1.sortBy(_%3).take(5)  先排序再取前面几个,类似于top
保存为文件
rdd1.saveAsTextFile


提交
spark-submit --class com.baidu.sh.xzq.workcount /sh_xingzhiqiang/share/original-spark-2.0.jar

 

DataFrame

val sc_sql=new org.apache.spark.sql.SQLContext(sc)
case class row(x:String,y:Int)
val rdd=sc.textFile("/user/hive/warehouse/temp.db/top_n").map(_.split(","))
val rdd1=rdd.map(x=>row(x(0),x(1).toInt))
rdd1.toDF.select("x").show

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值