百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

Spark 开窗函数中order By的作用(spark窗口函数原理)

ztj100 2024-10-28 21:13 32 浏览 0 评论

最近几天,受到打击了,总是被人问到 开窗函数中加入 order by 和 不加 order by 有什么区别。

例如 sum(x1) over (partition by x2 order by x1) 和 sum(x1) over (partition by x2)的结果一样吗?为什么?

我一开始觉得,你在 sum中后面加什么order by,反正都是获取累加的结果,加不加order by有什么影响?

后来我自己尝试运行,看了结果,的确不一样,怎么会这样,给大家看看结果:

这是输入数据:
+---+---+
| id| kk|
+---+---+
|  0|  1|
|  1|  1|
|  2|  1|
|  3|  2|
|  4|  2|
|  5|  2|
|  6|  2|
|  7|  3|
|  8|  3|
|  9|  3|
+---+---+
  
这是执行了  functions.sum("kk").over(Window.partitionBy("kk").orderBy("id")
+---+---+---+
| id| kk| dd|
+---+---+---+
|  0|  1|  1|
|  1|  1|  2|
|  2|  1|  3|
|  7|  3|  3|
|  8|  3|  6|
|  9|  3|  9|
|  3|  2|  2|
|  4|  2|  4|
|  5|  2|  6|
|  6|  2|  8|
+---+---+---+

+---+---+---+
| id| kk| dd|
+---+---+---+
|  0|  1|  3|
|  1|  1|  3|
|  2|  1|  3|
|  7|  3|  9|
|  8|  3|  9|
|  9|  3|  9|
|  3|  2|  8|
|  4|  2|  8|
|  5|  2|  8|
|  6|  2|  8|
+---+---+---+

大家可以看到,不一样

为什么呢?后面我是翻了spark的源码 和 看了执行计划才得到的答案。

.withColumn("dd", functions.sum("kk").over(Window.partitionBy("kk").orderBy("id") ) 它的物理执行计划是:

Window [sum(cast(kk#2 as bigint)) windowspecdefinition(kk#2, id#0L ASC NULLS FIRST, specifiedwindowframe(RangeFrame, unboundedpreceding$(), currentrow$())) AS dd#13L], [kk#2], [id#0L ASC NULLS FIRST]


.withColumn("dd", functions.sum("kk").over(Window.partitionBy("kk"))) 它的物理执行计划是:

Window [sum(cast(kk#2 as bigint)) windowspecdefinition(kk#2, specifiedwindowframe(RowFrame, unboundedpreceding$(), unboundedfollowing$())) AS dd#18L], [kk#2]


从这里就可以发现猫腻,

加入了order by之后,spark对于开窗函数,windowspecdefinition 选择了 RangeFrame,并且它的边界是 第一行 到当前行。

不加入order by之后,spark对于开窗函数,windowspecdefinition 选择了 RowFrame,并且它的边界是第一行到最后一行。

所以我们看到 加入order by之后的结果就是

+---+---+---+
| id| kk| dd|
+---+---+---+
|  0|  1|  1| 1
|  1|  1|  2| 1+1
|  2|  1|  3| 1+1+1
|  7|  3|  3| 3
|  8|  3|  6| 3+3
|  9|  3|  9| 3+3+3
|  3|  2|  2| 2frame
|  4|  2|  4| 2+2
|  5|  2|  6| 2+2+2
|  6|  2|  8| 2+2+2+2
+---+---+---+

因为结果都是首行到当前行的累加值。

那么结果很明确了,就是 加入 order by之后,spark底层选择 frame type会是 RangeFrame,并且默认它的边界就是 unboundedpreceding , currentrow。这就是加入order by的作用,之所以累加和不同,就是这个 RangeFrame和它的边界值搞得鬼。

那反过来,如果我还是使用 order by,但是我手动设置它的边界值,是 unboundedpreceding 和

unboundedfollowing,那样,执行的结果应该和 不加入order by的结果应该一样。

所以我又尝试了

.withColumn("dd", functions.sum("kk").over(Window.partitionBy("kk").orderBy("id")
    .rangeBetween(Long.MinValue,Long.MaxValue)
)
自己手动设定它的边界值,
运行结果就是
+---+---+---+
| id| kk| dd|
+---+---+---+
|  0|  1|  3|
|  1|  1|  3|
|  2|  1|  3|
|  7|  3|  9|
|  8|  3|  9|
|  9|  3|  9|
|  3|  2|  8|
|  4|  2|  8|
|  5|  2|  8|
|  6|  2|  8|
+---+---+---+

真的,这就是 真相了,加入 order by 和 不加入 order by的真相。

多看源码,其实和 底层 选择的 Frame 和 它的边界值 有关。

相关推荐

再说圆的面积-蒙特卡洛(蒙特卡洛方法求圆周率的matlab程序)

在微积分-圆的面积和周长(1)介绍微积分方法求解圆的面积,本文使用蒙特卡洛方法求解圆面积。...

python编程:如何使用python代码绘制出哪些常见的机器学习图像?

专栏推荐...

python创建分类器小结(pytorch分类数据集创建)

简介:分类是指利用数据的特性将其分成若干类型的过程。监督学习分类器就是用带标记的训练数据建立一个模型,然后对未知数据进行分类。...

matplotlib——绘制散点图(matplotlib散点图颜色和图例)

绘制散点图不同条件(维度)之间的内在关联关系观察数据的离散聚合程度...

python实现实时绘制数据(python如何绘制)

方法一importmatplotlib.pyplotaspltimportnumpyasnpimporttimefrommathimport*plt.ion()#...

简单学Python——matplotlib库3——绘制散点图

前面我们学习了用matplotlib绘制折线图,今天我们学习绘制散点图。其实简单的散点图与折线图的语法基本相同,只是作图函数由plot()变成了scatter()。下面就绘制一个散点图:import...

数据分析-相关性分析可视化(相关性分析数据处理)

前面介绍了相关性分析的原理、流程和常用的皮尔逊相关系数和斯皮尔曼相关系数,具体可以参考...

免费Python机器学习课程一:线性回归算法

学习线性回归的概念并从头开始在python中开发完整的线性回归算法最基本的机器学习算法必须是具有单个变量的线性回归算法。如今,可用的高级机器学习算法,库和技术如此之多,以至于线性回归似乎并不重要。但是...

用Python进行机器学习(2)之逻辑回归

前面介绍了线性回归,本次介绍的是逻辑回归。逻辑回归虽然名字里面带有“回归”两个字,但是它是一种分类算法,通常用于解决二分类问题,比如某个邮件是否是广告邮件,比如某个评价是否为正向的评价。逻辑回归也可以...

【Python机器学习系列】拟合和回归傻傻分不清?一文带你彻底搞懂

一、拟合和回归的区别拟合...

推荐2个十分好用的pandas数据探索分析神器

作者:俊欣来源:关于数据分析与可视化...

向量数据库:解锁大模型记忆的关键!选型指南+实战案例全解析

本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在...

用Python进行机器学习(11)-主成分分析PCA

我们在机器学习中有时候需要处理很多个参数,但是这些参数有时候彼此之间是有着各种关系的,这个时候我们就会想:是否可以找到一种方式来降低参数的个数呢?这就是今天我们要介绍的主成分分析,英文是Princip...

神经网络基础深度解析:从感知机到反向传播

本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在...

Python实现基于机器学习的RFM模型

CDA数据分析师出品作者:CDALevelⅠ持证人岗位:数据分析师行业:大数据...

取消回复欢迎 发表评论: