一:准备

1.源数据

  

2.上传数据

  

二:TopN程序编码

1.程序

 package com.ibeifeng.bigdata.spark.core

 import java.util.concurrent.ThreadLocalRandom

 import org.apache.spark.{SparkConf, SparkContext}

 /**
* 分组TopN:按照第一个字段分组;同一组中,按照第二个字段进行排序;每一组中,获取出现最多的前K个数据。
* Created by ibf on 01/15.
*/
object GroupedTopN {
def main(args: Array[String]): Unit = {
val conf = new SparkConf()
.setMaster("local[*]")
.setAppName("grouped-topn")
//.set("spark.eventLog.enabled", "true")
//.set("spark.eventLog.dir", "hdfs://hadoop-senior01:8020/spark-history") val sc = SparkContext.getOrCreate(conf) // ==========具体代码逻辑========================
// 原始数据存储的路径, 需要自己上传
val path = "/user/beifeng/spark/groupedtopk/groupsort.txt"
val K = 3 // 构建rdd
val rdd = sc.textFile(path) // rdd操作
val word2CountRDD = rdd
.filter((line: String) => {
// 过滤空字符串,所以非空的返回true
!line.isEmpty
})
.map(line => {
// 按照空格分隔字段
val arr = line.split(" ")
// 将数据转换为二元组
(arr(0), arr(1).toInt)
}) // 如果一个RDD被多次使用,该RDD需要进行缓存操作
word2CountRDD.cache() // 直接使用groupByKey函数进行统计,这种方式存在OOM的情况
/*
val resultRDD = word2CountRDD
.groupByKey() // 按照第一个字段进行分组
.map(tuple => {
// 同一组的数据中获取前K个元素
// 获取对应分组
val word = tuple._1
// 获取前K个元素(最大的k个元素), list默认排序是升序, 所以采用takeRight从后往前获取K个元素(此时的K个元素就是最大的K个元素); 最后对K个元素进行反转,最终结果元素是从大到小排序的
val topk = tuple._2.toList.sorted.takeRight(K).reverse
// 返回结果
(word, topk)
})
*/ /*
* groupByKey存在OOM异常
* 解决方案:采用两阶段聚合操作
* 两阶段聚合可以解决的一些常见:
* 1. 聚合操作中存储的OOM异常
* 2. 聚合操作中存在的数据倾斜问题
* 聚合操作:分区、排序、reduceByKey.....
* */
val random = ThreadLocalRandom.current()
val resultRDD2 = word2CountRDD
.map(tuple => {
// 第一阶段第一步:在key前加一个随机数
((random.nextInt(100), tuple._1), tuple._2)
})
.groupByKey() // 第一阶段的第二步:按照修改后的key进行聚合操作
.flatMap(tuple => {
// 第一阶段的第三步:对一组value进行聚合操作
// 获取对应分组
val word = tuple._1._2
// 获取前K个
val topk = tuple._2.toList.sorted.takeRight(K).reverse
// 返回结果
topk.map(count => (word, count))
})
.groupByKey() // 第二阶段第一步:按照原本的key进行聚合操作
.map(tuple => {
// 第二阶段第二步: 获取前k个元素
val word = tuple._1
val topk = tuple._2.toList.sorted.takeRight(K).reverse
// 返回结果
(word, topk)
}) // 结果输出
resultRDD2.foreach(println)
/*
resultRDD2.foreachPartition(iter => {
// foreachPartition该函数常用于将RDD的数据输出到第三方的数据存储系统中,比如:redis、mongoDB
/*
* 1. 创建连接
* 2. 对iter进行迭代,进行数据输出
* 3. 关闭连接
* */
iter.foreach(println)
})
*/ // 如果RDD有cache,需要去除cache
word2CountRDD.unpersist() // ==========具体代码逻辑======================== sc.stop()
}
}

2.结果

  

3.注意点

  Spark中不支持二次排序,如果想实现二次排序,需要根据业务的执行逻辑使用两阶段聚合来进行操作

二:优化

1.两阶段聚合

  

020 Spark中分组后的TopN,以及Spark的优化(重点)的更多相关文章

  1. 如何在spark中读写cassandra数据 ---- 分布式计算框架spark学习之六

    由于预处理的数据都存储在cassandra里面,所以想要用spark进行数据分析的话,需要读取cassandra数据,并把分析结果也一并存回到cassandra:因此需要研究一下spark如何读写ca ...

  2. Spark中的编程模型

    1. Spark中的基本概念 Application:基于Spark的用户程序,包含了一个driver program和集群中多个executor. Driver Program:运行Applicat ...

  3. Spark中的Phoenix Dynamic Columns

    代码及使用示例:https://github.com/wlu-mstr/spark-phoenix-dynamic phoenix dynamic columns HBase的数据模型是动态的,很多系 ...

  4. MySQL 排名、分组后组内排名、取各组的前几名 及排名后更新插入数据表中

    一.排名 /*普通排名:从1开始,顺序往下排*/ AS rank ) r ORDER BY score; /*并列排名:相同的值是相同的排名*/ SELECT cs.* , CASE WHEN @p= ...

  5. Spark:求出分组内的TopN

    制作测试数据源: c1 85 c2 77 c3 88 c1 22 c1 66 c3 95 c3 54 c2 91 c2 66 c1 54 c1 65 c2 41 c4 65 spark scala实现 ...

  6. sql-实现select取行号、分组后在分组内排序、每个分组中的前n条数据

    表结构设计: 实现select取行号 sql局部变量的2种方式 set @name='cm3333f'; select @id:=1; 区别:set 可以用=号赋值,而select 不行,必须使用:= ...

  7. [MySQL]MySQL数据库中如何查询分组后每组中的最后一条记录?

    原文地址:https://codedefault.com/s/how-can-i-retrieve-the-last-record-in-each-group-mysql 问题描述 比如,在MySQL ...

  8. SQL获取分组后取某字段最大一条记录(求每个类别中最大的值的列表)

    获取分组后取某字段最大一条记录 方法一:(效率最高) select * from test as a where typeindex = (select max(b.typeindex) from t ...

  9. 024 关于spark中日志分析案例

    1.四个需求 需求一:求contentsize的平均值.最小值.最大值 需求二:请各个不同返回值的出现的数据 ===> wordCount程序 需求三:获取访问次数超过N次的IP地址 需求四:获 ...

随机推荐

  1. Wannafly挑战赛21 E 未来城市规划

    传送门 题目中给的信息很难直接维护,但是可以考虑一条边对答案的贡献 在以\(x\)为根的子树里,如果一条边\(i\)的权值为\(w_i\),这条边深度更深的端点为\(to_i\),那么这条边对这个子树 ...

  2. mysql 案例~mysql元数据的sql统计

    一 简介:今天我们来收集下提取元数据的sql 二 前沿: information_schema  引擎 memory 元数据收集表 三 sql语句: 1#没有使用索引的表统计 SELECT t.TAB ...

  3. python - class类 (四) 三大特性之一 :继承

    继承: #继承 #什么时候用继承? # 1.当类之间有显著的不同,并且较小的类是较大的类的所需的组建时,用组合比较好. # 2.当类之间有很多相同的功能,提取这些共同的功能做成基类,用继承比较好 # ...

  4. 2018-2019-2 网络对抗技术 20165230 Exp2 后门原理与实践

    目录 1.实验内容 2.基础问题回答 3.常用后门工具实践 3.1netcat 3.2Meterpreter 3.3socat 4.实验过程 任务一:使用netcat获取主机操作Shell,cron启 ...

  5. Docker帮助命令

    ①docker version ②docker info ③docker --help

  6. python模块分析之logging日志(四)

    前言 python的logging模块是用来设置日志的,是python的标准模块. 系列文章 python模块分析之random(一) python模块分析之hashlib加密(二) python模块 ...

  7. 机器学习编程语言之争,Python夺魁

    机器学习编程语言之争,Python夺魁 随着科技的发展,拥有高容量.高速度和多样性的大数据已经成为当今时代的主题词.数据科学领域中所采用的机器学习编程语言大相径庭.究竟哪种语言最适合机器学习成为争论不 ...

  8. Python Tools for Machine Learning

    Python Tools for Machine Learning Python is one of the best programming languages out there, with an ...

  9. nodejs 数据库操作,消息的发送和接收,模拟同步

    var deasync = require('deasync'); //导入模板 var mysql=require('mysql'); var Stomp = require('stompjs'); ...

  10. 整理一下odoo10在windows系统下部署的流程

    odoo10环境搭建 所需依赖: Python3.5 odoo10.0 Node.js PostgreSQL 9.5 PyCharm 专业版 1.首先先安装好Python3.5,并设置好环境变量 2. ...