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

本文介绍了如何通过使用`partitionBy()`指定分区信息来优化Spark中的`join()`操作,以减少资源和时间消耗。当一个RDD数据量大而另一个小,join会导致全 Shuffle。通过预先分区并持久化大数据量的RDD,可以避免不必要的shuffle。另外,还可以通过广播小数据量的RDD并使用`map()`来进一步优化,避免join操作。

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)
}
内容概要:本文提出了一种基于极端梯度提升(XGBoost)算法的光伏阵列复合故障诊断方法,并提供了完整的Python代码实现。该方法充分利用XGBoost在分类任务中的高性能优势,针对光伏系统中常见的多种复合故障(如阴影遮挡、组件老化、断路与短路等)进行精准识别与分类。通过构建合理的特征工程,结合实际运行监测数据,模型能够有效区分单一故障与多重并发故障,显著提升了诊断的准确性与鲁棒性。研究体现了数据驱动方法在新能源系统智能运维中的关键作用,展示了机器学习技术在光伏系统状态监测、故障预警与健康管理方面的广阔应用前景; 适合人群:具备一定Python编程能力及机器学习基础知识的科研人员、电气工程及相关专业的硕士/博士研究生,以及从事光伏电站运维、智能诊断系统开发的工程技术人才; 使用场景及目标:① 实现对光伏阵列多类型复合故障的自动化、高精度诊断;② 掌握XGBoost在工业故障诊断场景下的建模流程、参数调优与性能评估方法;③ 构建可推广的数据驱动型新能源设备健康管理系统,提升运维效率与系统可靠性; 阅读建议:建议读者结合所提供的Python代码,深入理解从数据预处理、特征提取、模型训练到结果可视化的完整流程,建议在实际光伏监测数据上进行迁移验证,并可进一步对比其他机器学习模型(如随机森林、SVM、深度学习网络),以优化诊断系统的泛化能力与工程适用性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值