这是关于Spark中的窗口函数的问题。
假设我有这个DF
DATE_S | ID | STR | VALUE
-------------------------
1 | 1 | A | 0.5
1 | 1 | A | 1.23
1 | 1 | A | -0.4
2 | 1 | A | 2.0
3 | 1 | A | -1.2
3 | 1 | A | 0.523
1 | 2 | A | 1.0
2 | 2 | A | 2.5
3 | 2 | A | 1.32
3 | 2 | A | -3.34
1 | 1 | B | 1.5
1 | 1 | B | 0.23
1 | 1 | B | -0.3
2 | 1 | B | -2.0
3 | 1 | B | 1.32
3 | 1 | B | 523.0
1 | 2 | B | 1.3
2 | 2 | B | -0.5
3 | 2 | B | 4.3243
3 | 2 | B | 3.332
这只是一个例子!假设每个(ID,STR)有更多的DATE_S ,更多ID和STR ,并且每个(DATE_S,ID,STR)还有更多条目。显然,每个组合有多个值(DATE_S,ID,STR)
现在我这样做:
val w = Window.partitionBy("ID", "STR").orderBy("DATE_S").rangeBetween(-N, -1)
df.withColumn("RESULT", function("VALUE").over(w))
其中 N 可能导致包含大范围的行,从100到100000甚至更多,具体取决于(“ ID”,“ STR”)
结果将是这样
DATE_S | ID | STR | VALUE | RESULT
----------------------------------
1 | 1 | A | 0.5 | R1
1 | 1 | A | 1.23 | R1
1 | 1 | A | -0.4 | R1
2 | 1 | A | 2.0 | R2
3 | 1 | A | -1.2 | R3
3 | 1 | A | 0.523 | R3
1 | 2 | A | 1.0 | R4
2 | 2 | A | 2.5 | R5
3 | 2 | A | 1.32 | R6
3 | 2 | A | -3.34 | R7
1 | 1 | B | 1.5 | R8
1 | 1 | B | 0.23 | R8
1 | 1 | B | -0.3 | R9
2 | 1 | B | -2.0 | R10
3 | 1 | B | 1.32 | R11
3 | 1 | B | 523.0 | R11
1 | 2 | B | 1.3 | R12
2 | 2 | B | -0.5 | R13
3 | 2 | B | 4.3243| R14
3 | 2 | B | 3.332 | R14
存在相同的“结果”,因为对于具有相同(DATE_S,ID,ST)的每一行,用于“函数”计算的值都是相同的。
我的问题是这个
是否为每个ROW激发调用“函数” (多次重新计算相同的值),或者在每个范围(帧?)的值中计算一次,并粘贴它们在该范围内的所有行上?
感谢您的阅读:)
答案 0 :(得分:2)
根据您的数据,如果运行两次,结果可能不一样,因为没有明显的排序可能性。但是我们把它放在一边。
尽管有代码生成优化,但找不到它以您声明的方式检查下一次调用是否与下一行要处理的数据集相同。我从未读过这种优化。由于懒惰的评估方法而导致融合,但这是另一回事。因此,每行都会重新计算一次。
来源广泛:https://jaceklaskowski.gitbooks.io/mastering-spark-sql/spark-sql-functions-windows.html
...窗口函数的核心是为每个 表的输入行基于一组称为框架的行。每一个 输入行可以具有与之关联的唯一框架。 ...
...换句话说,在执行时,窗口函数会计算一个值 窗口中的每一行(根据窗口规范)。 ...
最大的问题是要有适当数量的分区用于并行处理,这很昂贵,但这是大数据。 partitionBy("ID", "STR")
是这里的线索,那是一件好事。