distribute by在spark中的一些应用
一.在二次排序当中的应用
1.1
说到排序当然第一想到的就是sort by和order by这两者的区别,也分情况。
在算子当中,两者没有区别,orderby()调用的也是sort。order by就是sort的别名。
/**
* Returns a new Dataset sorted by the given expressions.
* This is an alias of the `sort` function.
*
* @group typedrel
* @since 2.0.0
*/
@scala.annotation.varargs
def orderBy(sortExprs: Column*): Dataset[T] = sort(sortExprs : _*)
在spark sql语句中,则关系到是否全局排序。
https://spark.apache.org/docs/3.0.0/sql-ref-syntax-qry-select-orderby.html
The ORDER BY clause is used to return the result rows in a sorted manner in the user specified order. Unlike the SORT BY clause, this clause guarantees a total order in the output
ORDER BY子句用于按照用户指定的顺序以排序的方式返回结果行。与SORT BY子句不同,该子句保证输出中的总顺序
1.2
如果只想针对一个字段的排序时,这些貌似都没有问题。
但是如果想针对多个字段进行二次排序,三次排序呢?
select col1,col2 from table order by name,time
针对以上语句,我想根据名称以及时间进行排序,在一个spark 集群里运行并没有得到预期的值。
为什么order by在一个分布式计算里针对两个以上的字段进行排序达不到预期的效果呢?我觉得是因为,不同的name数据行分布在不同的节点或者分区上,order by只能保证各分区内的效果。查看结果也确实是,不同的name有一段有一个顺序的时间值,然后变成了另一个name,过一会儿,也跳会了原来的name区别。
结果就不贴出来了。
网上有过一些二次排序的方案,个人觉得使用distribute最简单。
DISTRIBUTE BY子句用于根据输入表达式对数据进行重新分区。
针对上面的order by在分布式环境下不能全局二次排序的情况,DISTRIBUTE BY可完美解决,因为它的作用就是针对某一字段,把相同的数据划分到同一分区。
然后数据在同一个分区了,那么再使用order by 或者sort by进行排序,二次三次排序都没有问题。
以下sql语句先对同name的划分到同一分区,然后针对name,time进行排序,可以得到预期效果。
select col1,col2 from table distribute name order by name time
二.
distribute by解决mappartition的迭代器里OOM的问题
2.1考虑一个业务场景。
有一个车辆数据,每天需要计算每个车的统计数据。很笼统。大概就是spark在凌晨读取前一天数据,然后按车辆ID分组进行计算。
第一想到的多半是group by id,然后在一个mapprittion接收一个迭代器进行循环处理。
dsInit.groupByKey(new MapFunction<DataSourceModel, String>() {
@Override
public String call(DataSourceModel dataSourceModel) throws Exception {
return dataSourceModel.getVin();
}
}, Encoders.STRING())
.flatMapGroups(new FlatMapGroupsFunction<String, DataSourceModel, Result>() {
@Override
public Iterator<Result> call(String key, Iterator<DataSourceModel> iterator) throws Exception {
//iterator迭代处理
}
但这样的风险很明显,就是OOM的风险。spark等大数据框架最大的特点就在于管道处理。不怕处理的数据量大,也不怕服务器资源少(满足最低配置),可以一点一点处理,再汇总,内存放不下就落磁盘。但mappartition的iterator相当于就是把当前分区的数据全部加载到内存当中来处理,如果当前分区数据量过大,那么OOM就是必然的。
2.2 如果当前分区数据量过大,可以使用其它方案。
2.2.1
使用DISTRIBUTE BY将数据按字段进行分区,通过2.1我们已经能够确认这一点。
在这基础上,再进行mappartition,同样是接收到一个iterator进行处理,没有OOM风险。
经实证,同样的数据,使用group by加FlatMapGroupsFunction直接OOM,
使用
select col1,col2 from table DISTRIBUTE BY id sort by id,time....
得到一个dataset,再进行MapGroupsFunctiont可有效避免OOM风险。
2.2.2
这里还涉及到一个mappartion真的比map效率高吗
https://blog.csdn.net/weixin_29531897/article/details/114732360
这篇文章作者经过测试,mappartion并不一定效率高,而且有OOM风险。
在文章里也提到另一个解决方案。
大概是利用scala的iterator进行map.
def mapFunc[T, U](iterator: Iterator[T], f2: T => (U)) = { iterator.map(x => { f2(x) }) }
或者直接在mapprition里的iterator进行iterator.map(x => { //业务逻辑处理 })
很遗憾,经测试,同样的上述的数据集,这两种方法都直接OOM。并没有达到文章里说的效果。
2.2.3
在一些特定的业务场景下可以使用reduceGroups
相当于rdd的reduce,两两处理,最终得到一条结果。
reduceGroups(new ReduceFunction<ChargeIteratorMap>() {
@Override
public ChargeIteratorMap call(ChargeIteratorMap v1, ChargeIteratorMap v2) throws Exception {
return service(v1, v2);
}
})
如上述业务场景,可先分组并进行排序,再使用reduceGroups当前数据与前一条数据进行计算累加计算,并把临时结果通过java bean或者case class或者第三方流水保存。
注意:reduceGroups在只有一条数据的时候不执行。
参考:
https://spark.apache.org/docs/3.0.0/sql-ref-syntax-qry-select-distribute-by.html
distribute by在spark中的一些应用的更多相关文章
- Spark中常用工具类Utils的简明介绍
<深入理解Spark:核心思想与源码分析>一书前言的内容请看链接<深入理解SPARK:核心思想与源码分析>一书正式出版上市 <深入理解Spark:核心思想与源码分析> ...
- SPARK 中 DriverMemory和ExecutorMemory
spark中,不论spark-shell还是spark-submit,都可以设置memory大小,但是有的同学会发现有两个memory可以设置.分别是driver memory 和executor m ...
- Scala 深入浅出实战经典 第65讲:Scala中隐式转换内幕揭秘、最佳实践及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第61讲:Scala中隐式参数与隐式转换的联合使用实战详解及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载: 百度云盘:http://pan.baidu.com/s/1c0noOt ...
- Scala 深入浅出实战经典 第60讲:Scala中隐式参数实战详解以及在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-87讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第51讲:Scala中链式调用风格的实现代码实战及其在Spark中应用
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第48讲:Scala类型约束代码实战及其在Spark中的应用源码解析
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第47讲:Scala多重界定代码实战及其在Spark中的应用
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Scala 深入浅出实战经典 第42讲:scala 泛型类,泛型函数,泛型在spark中的广泛应用
王家林亲授<DT大数据梦工厂>大数据实战视频 Scala 深入浅出实战经典(1-64讲)完整视频.PPT.代码下载:百度云盘:http://pan.baidu.com/s/1c0noOt6 ...
- Spark中的编程模型
1. Spark中的基本概念 Application:基于Spark的用户程序,包含了一个driver program和集群中多个executor. Driver Program:运行Applicat ...
随机推荐
- el与data的两种写法
el的两种写法 Vue初始化(被创建)后会判断有无el 有el:创建Vue实例对象的时候配置el属性 无el:通过vm.$mount('#root')指定el的值 data的两种写法 对象式:data ...
- C# 通过StreamWriter输出的TXT流文件,前缀带EF BB BF
好久没有动笔写博客了,这个小天地被我闲置的放了好久好久,接下来要慢慢捡起来了. 备注:通过C#的StreamWriter类输出一个TXT流文件,供下位机工程师使用,发现打开的16进制文件中,默认添加了 ...
- 德国坦克傲龙7.1PCIe | 魔音师 声源PCIe MaX 声卡驱动皮肤
适用于德国坦克傲龙7.1PCIe和魔音师 声源PCIe MaX 声卡驱动皮肤的皮肤. 皮肤使用方法:退出声卡驱动程序(托盘图标右键退出),之后删除声卡驱动目录里面的TERRATECAudioCente ...
- 项目优化-CDN缓存
名次解释 CDN(Content Delivery Network)内容分发网络. CDN出现背景: 客户端从源站点获取数据,当服务端访问流量较为拥挤的时候 可能出现缓慢卡顿的现象,为了解决这个问题, ...
- python协程详细解释以及例子
目录 1.协程 1.1greenlet实现协程 1.2yield关键字实现协程 1.3使用asyncio模块实现协程 1.4async & await关键字实现协程 2.协程意义 3.异步编程 ...
- Python 霸榜的一周,又有什么新 AI 力作呢?「GitHub 热点速览」
GPT 带火了一波语言模型,LLaMA 和 Alpaca 也在持续发力.依旧是各类 GPT 后缀霸榜 GitHub trending 的一周,为此特推部分专门收录了两个比较不错的 GPT 应用.而作为 ...
- ECC(SM2) 简介及 C# 和 js 实现【加密知多少系列】
〇.简介 椭圆曲线密码学(Elliptic curve cryptography:ECC),一种建立公开密钥加密的演算法,基于椭圆曲线数学.利用有限域上椭圆曲线的点构成的 Abel 群离散对数难解性, ...
- ACM-NEFU-2020大一寒假培训三(暴力)
A.二倍的问题 Description 给定2到15个不同的正整数,你的任务是计算这些数里面有多少个数对满足:数对中一个数是另一个数的两倍.比如给定1 4 3 2 9 7 18 22,得到的答案是3, ...
- .net core基于HttpClient实现的网络请求库
Soda.Http 基于HttpClient封装的 Http 请求库.如果有什么好想法,可以提 Issue 或者 Pr.,如果想要使用,直接在nuget搜索Soda.Http即可. Github项目地 ...
- 运输问题—R实现
table { margin: auto } 运输问题 随着社会和经济的不断进步,现代物流业蓬勃发展,如何充分利用时间.信息.仓储.配送和联运体系创造更多的价值,是物流运作必须解决的问题.运输问题(t ...