Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala Spark中的用户定义聚合函数UDAF何时合并_Scala_Apache Spark_Apache Spark Sql_User Defined Aggregate - Fatal编程技术网

Scala Spark中的用户定义聚合函数UDAF何时合并

Scala Spark中的用户定义聚合函数UDAF何时合并,scala,apache-spark,apache-spark-sql,user-defined-aggregate,Scala,Apache Spark,Apache Spark Sql,User Defined Aggregate,我想知道Spark将在什么情况下作为UDAF函数的一部分执行合并 动机: 我在Spark项目中的一个窗口上使用了很多UDAF函数。我经常想回答这样的问题: 在30天的窗口期内,信用卡交易与当前交易在同一国家发生了多少次 窗口将从当前事务开始,但不会将其包括在计数中。它需要当前交易的价值,才能知道在过去30天内要计算哪个国家 val rollingWindow = Window .partitionBy(partitionByColumn) .orderBy(orderBy

我想知道Spark将在什么情况下作为UDAF函数的一部分执行合并

动机: 我在Spark项目中的一个窗口上使用了很多UDAF函数。我经常想回答这样的问题:

在30天的窗口期内,信用卡交易与当前交易在同一国家发生了多少次

窗口将从当前事务开始,但不会将其包括在计数中。它需要当前交易的价值,才能知道在过去30天内要计算哪个国家

val rollingWindow = Window
      .partitionBy(partitionByColumn)
      .orderBy(orderByColumn.desc)
      .rangeBetween(0, windowSize)

df.withColumn(
  outputColumnName,
  customUDAF(inputColumn, orderByColumn).over(rollingWindow))
我写了我的customUDAF来计算。我总是使用
.orderBy(orderByColumn.desc)
,多亏了
.desc
,当前事务在计算过程中显示为窗口中的第一个事务

UDAF函数需要实现
merge
函数,该函数在并行计算中合并两个中间聚合缓冲区。如果发生任何合并,对于不同的缓冲区,我的
当前事务
可能不相同,UDAF的结果将不正确

我编写了一个UDAF函数,它统计数据集上的合并数,并只保留窗口中的第一个事务与当前事务进行比较

 class FirstUDAF() extends UserDefinedAggregateFunction {

  def inputSchema = new StructType().add("x", StringType)
    .add("y", StringType)

  def bufferSchema = new StructType()
    .add("first", StringType)
    .add("numMerge", IntegerType)

  def dataType = new StructType()
    .add("firstCode", StringType)
    .add("numMerge", IntegerType)

  def deterministic = true

  def initialize(buffer: MutableAggregationBuffer) = {
    buffer(0) = ""
    buffer(1) = 1
  }

  def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
    if (buffer.getString(0) == "")
      buffer(0) = input.getString(0)

  }

  def merge(buffer1: MutableAggregationBuffer, buffer2: Row) = {
    buffer1(1) = buffer1.getInt(1) + buffer2.getInt(1)
  }

  def evaluate(buffer: Row) = buffer
}
当我在一个有16个cpu的本地主机上用spark 2.0.1运行它时,从来没有任何合并,窗口中的第一个事务始终是当前事务。这就是我想要的。在不久的将来,我将在一个x100更大的数据集和真正的分布式Spark集群上运行我的代码,并想知道合并是否会在那里发生

问题:

  • UDAF在哪些情况/条件下进行合并
  • 带有orderBy的Windows是否有合并
  • 有没有可能告诉Spark不要进行合并
UDAF在哪些情况/条件下进行合并

merge
在洗牌(“减少侧聚合”)之后合并聚合函数(“映射侧聚合”)的部分应用程序时调用

带有orderBy的Windows是否有合并

在当前的实现中,从不使用。至于现在,窗口函数只是花哨的
groupByKey
,没有部分聚合。这当然是实现细节,将来可能会更改,恕不另行通知

有没有可能告诉Spark不要进行合并

事实并非如此。但是,如果数据已经由聚合键分区,则不需要
merge
,只使用
combine

最后:

在30天的窗口期内,信用卡交易与当前交易在同一国家发生了多少次


不调用
UDAFs
或窗口函数。我可能会使用
o.a.s.sql.functions.window
创建滚动窗口,按用户、国家/地区和窗口进行聚合,并加入输入。

感谢您的澄清。我接受你的回答。关于你的最后一点,我不确定我是否理解我将如何做到这一点。你能详细说明一下吗?如何按窗口聚合?我按用户划分,按日期排序,并计算窗口中当前事务(相对于窗口当前,如sql中的当前行)中某个国家/地区发生的次数。对于每笔交易,这个国家是不同的。