前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SparkSql窗口函数源码分析(第一部分)

SparkSql窗口函数源码分析(第一部分)

作者头像
数据仓库践行者
发布2022-11-25 19:59:18
9260
发布2022-11-25 19:59:18
举报

这篇梳理一下sparksql实现窗口函数用到的类。

代码语言:javascript
复制
select  
    a,
    row_number() over(partition by a order by b desc ) as rn 
from testdata2

上面的语句主要分两部分

  • window函数部分(row_number)
  • 窗口定义部分(over)
代码语言:javascript
复制
select  
    a,
    row_number() over(partition by a order by b desc ) as rn 
from testdata2

--------unresolved logical plan--------
'Project ['a, 'row_number() windowspecdefinition('a, 'b DESC NULLS LAST, unspecifiedframe$()) AS rn#10]
+- 'UnresolvedRelation [testdata2], [], false

从执行计划能够了解到sparksql描述窗口函数时用到的类的结构。

窗口函数的类结构

WindowExpression :描述该expression是一个windowExpression,继承BinaryLike,是一个二元树。

1、window函数部分--windowFunction

windows函数部分就是所要在窗口上执行的函数。

WindowFunction

  • AggregateWindowFunction --聚合函数、分析窗口函数(Analytic functions)cume_dist函数计算当前值在窗口中的百分位数
  • OffsetWindowFunction --位移(lag、lead),非聚合函数
  • agg_funcs (一般聚合函数)

count 、sum、avg、first_value

WindowFunctionType

描述窗口函数是SQL窗口函数还是Python用户定义的窗口函数。

SQL

Python

2、窗口定义部分

WindowSpec

窗口函数定义的接口类(在OVER子句或Window子句中指定)

  • WindowSpecDefinition:定义了一个窗口函数应该包含哪些元素(定义了输入行的分区方式(按哪个字段分区)、定义分区内数据的该怎么排序(SortOrder类,按哪个字段排,升序还是降序)、定义了分区中的窗口框架(WindowFrame类))
  • WindowSpecReference:代表引用一个窗口函数,比如下面这种用法,这种写法的好处就是:over 后面内容如果相同的话,可以只用写一次
代码语言:javascript
复制
select  a,
        row_number() over wd as rn,
        sum(1) over wd as num
from    testdata2
window  wd as(partition by a order by b desc)

vs

select  a,
        row_number() over(partition by a order by b desc ) as rn,
        sum(1) over(partition by a order by b desc)  as num
from    testdata2

上面这两种只是写法不同,在效率上完全一样(可以通过对比物理执行计划得到)。

代码语言:javascript
复制
== Physical Plan ==
Project [a#3, rn#10, num#11L]
+- Window [row_number() windowspecdefinition(a#3, b#4 DESC NULLS LAST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS rn#10, sum(1) windowspecdefinition(a#3, b#4 DESC NULLS LAST, specifiedwindowframe(RangeFrame, unboundedpreceding$(), currentrow$())) AS num#11L], [a#3], [b#4 DESC NULLS LAST]
   +- SerializeFromObject [knownnotnull(assertnotnull(input[0, org.apache.spark.sql.test.SQLTestData$TestData2, true])).a AS a#3, knownnotnull(assertnotnull(input[0, org.apache.spark.sql.test.SQLTestData$TestData2, true])).b AS b#4]
      +- Scan[obj#2]

== Physical Plan ==
Project [a#3, rn#10, num#11L]
+- Window [row_number() windowspecdefinition(a#3, b#4 DESC NULLS LAST, specifiedwindowframe(RowFrame, unboundedpreceding$(), currentrow$())) AS rn#10, sum(1) windowspecdefinition(a#3, b#4 DESC NULLS LAST, specifiedwindowframe(RangeFrame, unboundedpreceding$(), currentrow$())) AS num#11L], [a#3], [b#4 DESC NULLS LAST]
   +- SerializeFromObject [knownnotnull(assertnotnull(input[0, org.apache.spark.sql.test.SQLTestData$TestData2, true])).a AS a#3, knownnotnull(assertnotnull(input[0, org.apache.spark.sql.test.SQLTestData$TestData2, true])).b AS b#4]
      +- Scan[obj#2]

WindowSpecDefinition

这部分就是over里面的内容了里面也有三部分

  • partition by
  • order by
  • ROWS | RANGE BETWEEN

前两部分就是把数据分区然后在分区内排序,排好了序才能很好的定位出我们需要向前或者向后取哪些数据来参与计算。这第三部分就是确定你需要哪些数据了。

代码语言:javascript
复制
case class WindowSpecDefinition(
    partitionSpec: Seq[Expression],
    orderSpec: Seq[SortOrder],
    frameSpecification: WindowFrame)
WindowFrame:窗口框架定义

UnspecifiedFrame:没有指定的窗口,生成未解析的逻辑执行计划时,用该类做为占位符,来说明这个地方是个窗口。

SpecifiedWindowFrame:指定的窗口,二元树。

代码语言:javascript
复制
case class SpecifiedWindowFrame(
    frameType: FrameType,
    lower: Expression,
    upper: Expression)
  extends WindowFrame with BinaryLike[Expression]
FrameType

用于表示窗框类型的特征。

  • RowFrame:用于处理分区中的行,按照距离来取。
    • ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW就是取从最开始到当前这一条数据,row_number()这个函数就是这样取的
    • ROWS BETWEEN 2 PRECEDING AND 2 FOLLOWING代表取前面两条和后面两条数据参与计算,比如计算前后五天内的移动平均就可以这样算.
  • RangeFrame:以当前值为锚点进行计算。比如RANGE BETWEEN 20 PRECEDING AND 10 FOLLOWING当前值为50的话就去前后的值在30到60之间的数据。
SpecialFrameBoundary

用于表示窗框中使用的特殊边界的特征。

  • UnboundedPreceding:UNBOUNDED PRECEDING
  • UnboundedFollowing:UNBOUNDED FOLLOWING
  • CurrentRow:CURRENT ROW
本文参与?腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-08-30,如有侵权请联系?cloudcommunity@tencent.com 删除

本文分享自 数据仓库践行者 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体分享计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、window函数部分--windowFunction
    • WindowFunction
      • WindowFunctionType
      • 2、窗口定义部分
        • WindowSpec
          • WindowSpecDefinition
            • WindowFrame:窗口框架定义
            • FrameType
            • SpecialFrameBoundary
        相关产品与服务
        数据库
        云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
        http://www.vxiaotou.com