Spark-键值对RDD
来源:互联网 发布:房产营销软件下载 编辑:程序博客网 时间:2024/06/05 14:08
键值对RDD是许多操作所需的常见数据类型 ,通常用来做聚合计算。
创建RDD
在scala中可将一个返回二元组的RDD隐式转换成pair rdd。
val input2 = sc.parallelize(List("1,a","2,b","3,c"))val r2 = input2.map(x=>{val temp = x.split(","); (temp(0), temp(1))})
r2支持所有pair rdd的操作。
对于Java,没有隐式转换,需要通过mapToPair函数来显示的将RDD转换为Pair RDD
PairFunction<String, String, String> pf = new PairFunction<String, String, String>(){ public Tuple2<String, String> call(String s){ return new Tuple2<String, String>(s.split(" ")[0], s.split(" ")[1]) }}JavaPairRDD<String, String> pair = lines.mapToPair(pf)
RDD的转换操作
聚合操作
当数据以键值对的形式组织的时候,聚合具有相同键的元素进行一个统计操作是很常见的。
reduceByKey:val input3 = sc.parallelize(List("23,zhangsan","23,lisi","24,wangwu","24,zhaoliu","24,zhouqi"))input3.reduceByKey((x, y) => x + y)("23“, zhangsan,lisi")("24","wangwu,zhaoliu,zhouqi")
数单词:val input = sc.textFile("hdfs://hbase:900/test/wc.txt")val words = input.flatMap(line=> line.split(" "))val result = words.map(w=>(w, 1)).reduceByKey((x, y) => x + y)
分组
根据Key对Value进行分组。对于一个类型为K的键和类型为V的值的RDD,进行分组后得到的结果是K, Iterator[V]
,
val input3 = sc.parallelize(List("23,zhangsan","23,lisi","24,wangwu","24,zhaoliu","24,zhouqi"))val result = input3.groupByKey()#得到的结果是("23",List("zhangsan", "lisi"))("24",List("wangwu", "zhaoliu", "zhouqi"))
链接
链接是最常见的数据集合间的操作之一,常用的操作有:join, leftOuterJoin, rightOuterJoin
val set1 = sc.parallelize(List("zhangsan, 23","lisi, 24", "wangwu,34"))val set2 = sc.parallelize(List("zhangsan,beijing","wangwu,shanghai","zhaoliu,hangzhou"))val p1 = set1.map(x=>(x.split(",")(0), x.split(",")(1)))val p2 = set2.map(x=>(x.split(",")(0), x.split(",")(1)))p1.join(p2)#结果("zhangsan","23,peking")("wangwu","34,shanghai")p1.leftOuterJoin(p2)#结果("zhangsan","23,peking")("lisi","24,null")("wangwu","34,shanghai")p1.rightOuterJoin(p2)("zhangsan","23,peking")("wangwu","34,shanghai")("zhaoliu","null,hangzhou")
数据排序
很多时候,让数据排好序是很有用的,尤其是生成下游输出时。可以利用函数sortByKey(ascending)
函数对某个key的值进行排序。
#在scala中,以字符串顺序对整数进行自定义排序val set1 = sc.parallelize(List("zhangsan, 23","lisi, 24", "wangwu,34"))val p1 = set1.map(x=>(x.split(",")(0), Integer.parse(x.split(",")(1))))#自定义隐式转换implicit val sortIntegerByString = new Ordering[Int]{ override def compare(a:Int, b:Int):Int = { a.toString.compare(b.toString) }}
行动操作
数据分区
在分布式程序中,节点之间网络通信的代价是相当大的,通过数据分区可以获得最少的网络传输,极大提升整体性能。
Spark中所有的键值对RDD都可以进行分区,Spark会根据一个针对键的函数进行分组,并保证分组结果相同的节点落在同一个节点上。
举例说明,内存中一个大表,当中存放了用户信息(userid, userinfo)
,userinfo中包含了一个用户所订阅的主题列表,一个存放用户在5分钟内访问网站访问情况表(userid, linkinfo)
,如果想对用户访问其未订阅的主题页面的情况进行统计,可以使用join操作来实现,需要把userinfo和linkinfo根据有序分组。
val sc = new SparkContext(...)val userData = sc.sequenceFile[UserID, UserInfo]("hdfs://..").persist()#处理主函数def processNewLogs(logFileName: String){ val event = sc.sequenceFile[UserID,UserLink](logFileName) val joined = userData.join(event) val offTopicEvents = joined.filter{ case (userId,(userInfo, linkInfo)) => !userInfo.topics.contains(linkInfo.topic) }.count() println(offTopicEvents)}
上面的代码存储一个问题,每次调用processNewLogs函数的时候,都会在userData上调用join,而join会触发对userData的重新分区,虽然每次的分区结果都一样,同时,由于userData中包含的数据量很大,这会给系统带来很大的敷在压力。
要解决这个问题就需要对userData进行分区后再持久化,这样,userData就会被分区后持久化到不同的节点上,网络传输的数据量大大减少
partitionBy:val sc = new SparkContext(...)val userData = sc.sequenceFile[UserID, UserInfo]("hdfs://..").partitionBy(new HashPartitioner(100)).persist()
获取分区的方式
RDD.partitioner
val input = sc.parallelize(List(1,2,3,4,5))val partitioned = input.partitiionBy(new spark.HashPartitioner(2))val partitioner = partitioned.partitioner#判断partitioner是否有值val judge = partition.isDefined#获取分区数val value = partitioner.get()
自定义分区
Spark允许提供一个自定义的Partitioner对象来控制RDD的分区,进而利用领域知识更进一步减少网络开销。
…
- Spark-键值对RDD
- Spark 键值对RDD操作
- Spark入门(五):键值对RDD
- Spark 的键值对(pair RDD)操作,Scala实现
- Spark学习之键值对(pair RDD)操作
- 键值对RDD
- Spark之键值RDD转换
- spark RDD算子(四)之创建键值对RDD mapToPair flatMapToPair
- Spark学习之键值对(pair RDD)操作(3)
- spark RDD算子(五)之键值对聚合操作 combineByKey
- spark RDD算子(六)之键值对聚合操作reduceByKey,foldByKey,排序操作sortByKey
- spark RDD算子(七)之键值对分组操作 groupByKey,cogroup
- spark RDD算子(八)之键值对关联操作 subtractByKey, join, rightOuterJoin, leftOuterJoin
- Spark常用函数讲解--键值RDD转换
- Spark常用函数之键值RDD转换
- 键值对RDD的创建方式
- spark键值对操作(一)
- Spark 键值对的操作
- 1001-1100
- HDU 5961 传递 图论 BFS (2016CCPC 合肥 A题)
- Java EE基础知识1
- C/C++调用约定
- 1101-1200
- Spark-键值对RDD
- BZOJ 1588 营业额统计 Splay
- 弗罗贝尼乌斯范数(Frobenius norm)
- DDMS和TraceView的区别
- 多态、继承的概念
- Java创建多线程的三种方式
- 1201-1300
- HDU 3487 Play With Chain Splay树 区间处理
- 小伙的java之旅(2)