Learning Spark 笔记(六) -- 指定分区信息改善join()等的操作

原创 2016年08月30日 08:40:35

9 . 默认情况下,join()操作会对两个RDD的主键做哈希以分区,通过网络将主键相同的元素发送到同一台机器上,然后根据相同的主键再进行连接。例子如下:

val sc = new SparkContext()
val userData = sc.sequenceFile[UserID,LinkInfo]("hdfs://...").persist
def processNewLogs(logFileName:String){
    val events = sc.sequenceFile[UserID, LinkInfo](logFileName)
    //RDD of (UserID,(UserInfo,LinkInfo)) pairs
    val joined = usersData.join(events)
    val offTopicVisits = joined.filter {
        // Expand the tuple into its components
        case (userId, (userInfo, linkInfo)) => 
            !userInfo.topics.contains(linkInfo.topic)
    }.count()
    println("Number of visits to non-subscribed opics: " + offTopicVisits)
}

这样的弊端是,两个RDD都会进行shuffle,资源和时间的消耗比较严重。如下图所示:
这里写图片描述
如果userData是一个大数据量、events是一个小数据量的话,每一次join()操作就会进行一次shuffle,这样的弊端体现的会更明显。为解决这个问题,我们可以利用partionBy()来指定分区信息。代码修改如下:

...
val userData = sc.sequenceFile[UserID,LinkInfo]("hdfs://...")
//指定分区信息为100个哈希分区
.partionBy(new HashPartiotioner(100))
//持久化操作,没有持久化等于白做指定分区信息的操作
.persist
...

在之后的join()操作,由于userData含有分区信息,且joined会有和userData一样的分区信息,那么userData就不会有shuffle。比如此处的userData和joined都有HashPartitioner信息,那么userData和joined中的元素只要key相同,就一定会在同一台机器上,所以userData中的数据只会是在本地移动。还一个值得注意的地方是,partionBy()操作也是shuffle,所以在指定分区信息后必须要有持久化操作。如果没有持久化操作,每次执行都会有partitionBy()的shuffle操作,那么就等于啥也没做甚至平白无故又增添shuffle。变化如下图所示:
这里写图片描述

还有另一种改进的方法也可以避免大数据量RDD的shuffle,那就是广播小数据量RDD,弃用join()操作,使用map()操作完成相同功能的操作。

def processNewLogs(logFileName:String){
    val events = sc.sequenceFile[UserID, LinkInfo](logFileName)
    val small = sc.brocast(events)
    //RDD of (UserID,(UserInfo,LinkInfo)) pairs
    val joined = userData.map(x=>{
        val ss = small.value
        ss.map(y=>{
            var tmp:(String,(String,String)) = null
            if(x._1 == y)
                tmp = (x._1,(x._2,y._2))
            tmp
        })
    })
    val offTopicVisits = joined.filter {
        // Expand the tuple into its components
        case (userId, (userInfo, linkInfo)) => 
            !userInfo.topics.contains(linkInfo.topic)
    }.count()
    println("Number of visits to non-subscribed opics: " + offTopicVisits)
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

spark自定义分区及使用方法

spark自定义分区及使用方法

spark的优化-控制数据分区和分布

数据分区: 在分布式集群里,网络通信的代价很大,减少网络传输可以极大提升性能。 mapreduce框架的性能开支主要在io和网络传输,io因为要大量读写文件,它是不可避免的,但是网络传输是可以避免...

Spark——数据分区(进阶)

对数据集在节点间的分区进行控制是Spark的一个特性之一。在分布式程序中通信的开销很大,和单节点的程序需要为记录集合选择合适的数据结构一样,Spark程序可以通过控制RDD分区方式来减少通信开销。只有...

Spark自定义分区(Partitioner)

转自:http://www.iteblog.com/archives/1368 我们都知道Spark内部提供了HashPartitioner和RangePartitioner两种分区策略,这两种...

Spark基础随笔:分区详解

RDD分区的一个分区原则:尽可能是得分区的个数等于集群核心数目 下面我们仅讨论Spark默认的分区个数,这里分别就parallelize和textFile具体分析其默认的分区数 无论是本地模式、Sta...

JAVA查看内存使用情况

一、使用JAVA类库。

guava之ImmutableMap使用实例及好处

ImmutableMap 的作用就是:可以让java代码也能够创建一个对象常量映射,来保存一些常量映射的键值对。 分析以下情景,来具体讨论这个的好处。 以下是在js前台的代码,假设现在有需求如下: 根...

Spark API编程动手实战-07-join操作深入实战

我们在hdfs的/data/join创建两个文件: 上传第一个文件名称为1.txt 内容第一列是日期,第二列uid(普通用户id) 上传第二个文件名称为2.txt 内容第一列是日期,第二列u...

2-2、spark的union和join操作演示

spark的union和join操作演示 union简介: 通常如果我们需要将两个select语句的结果作为一个整体显示出来,我们就需要用到union或者union all关键字。union(或称...

Spark算子:RDD键值转换操作(4)–cogroup、join

关键字:Spark算子、Spark RDD键值转换、cogroup、join cogroup ##参数为1个RDD def cogroup[W](other: RDD[(K, W)]): RDD[(K...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Learning Spark 笔记(六) -- 指定分区信息改善join()等的操作
举报原因:
原因补充:

(最多只允许输入30个字)