当数组列包含的值超过阈值时,如何编写Spark优化来重新计算数据帧? Spark 2.1.0和Scala 2.10.6
我一直在寻找有关使用自定义规则扩展Spark Catalyst优化的教程和帮助。我发现的所有示例都非常基本,通常使用与1的乘法作为示例来显示逻辑规则。 我想问的是,是否可以为以下情况编写自定义规则 我有一个数据帧,在一列(列2)中有一个数组。该数组每行包含N个值。我需要用一个新值M重新计算这个数据帧,这样数组现在将包含M个值。现在,我想应用的优化是,如果N>M,策略应该只返回具有前M个值的数据帧,而不是重新计算整个数据帧。否则调用函数来计算数据帧。所以基本上当数组列包含的值超过阈值时,如何编写Spark优化来重新计算数据帧? Spark 2.1.0和Scala 2.10.6,scala,apache-spark,apache-spark-sql,Scala,Apache Spark,Apache Spark Sql,我一直在寻找有关使用自定义规则扩展Spark Catalyst优化的教程和帮助。我发现的所有示例都非常基本,通常使用与1的乘法作为示例来显示逻辑规则。 我想问的是,是否可以为以下情况编写自定义规则 我有一个数据帧,在一列(列2)中有一个数组。该数组每行包含N个值。我需要用一个新值M重新计算这个数据帧,这样数组现在将包含M个值。现在,我想应用的优化是,如果N>M,策略应该只返回具有前M个值的数据帧,而不是重新计算整个数据帧。否则调用函数来计算数据帧。所以基本上 Rule (distance:Dat
Rule (distance:Dataframe, M:int){
distance.registerTempTable("tab1")
val N=sqlContext.sql("select size(_2) from tab1")
if(N>M){
// Query to select only top M values from column _2 to create distanceNew
return distanceNew
}else{
//call function to calculate distance from scratch (A time consuming process)
return getNNeighbors(distance,M)
}
}
可以在Spark Catalyst中编写这样的自定义规则吗?如果可以,我可以获得一些关于如何执行的指导吗?或者有没有其他方法可以基于Spark SQL上的模式匹配来定义自定义运行时优化规则
我已经编写了一个函数来实现这一点,但我的目标是在一些优化模式匹配API中编写它,以证明可以编写通用规则来优化算法的概念。如果我正确理解了您的问题,如果条件匹配,您希望在
数据帧中重新创建数组。正确的?如果是这种情况,则不需要重新创建dataframe
,只需使用udf
函数
以下不是完整的解决方案,但应该会有所帮助
定义udf
函数,假设array
为double
值
def testUdf = udf((value: Array[Double], M : Int) => {
val N = value.size
if(N > M) //return the new array
else //return the array you need
})
并用下面的代码调用它
dataframe.withColumn("column 2 name", testUdf(dataframe("column 2 name")))
如果我正确理解了您的问题,您希望在数据帧中重新创建数组
,前提是条件匹配。正确的?如果是这种情况,则不需要重新创建dataframe
,只需使用udf
函数
以下不是完整的解决方案,但应该会有所帮助
定义udf
函数,假设array
为double
值
def testUdf = udf((value: Array[Double], M : Int) => {
val N = value.size
if(N > M) //return the new array
else //return the array you need
})
并用下面的代码调用它
dataframe.withColumn("column 2 name", testUdf(dataframe("column 2 name")))
我真的不认为您的案例与Spark SQL的优化器规则(或其批次)有任何关系,因为优化规则必须处理(业务)数据的内容,而不是查询或数据集的结构。这不是一个优化规则,而是一个数据集转换
我认为它不值得一个新的优化规则
话虽如此,您为什么不做以下操作:
// check the length of the array column
val theArrayColumn = ...
val size = distance.select(size(theArrayColumn) as "size").orderBy("size").as[Int].head
val inputDF = if (size > M) {
recalculateDistance()
} else {
// we're fine
distance
}
getNNeighbors(inputDF)
如果您更详细地描述getNNeighbors
,那可能会更简单
size
是中的一个函数。我真的不认为您的案例与Spark SQL的优化器规则(或其批处理)有任何关系,因为优化规则必须处理(业务)数据的内容,而不是查询或数据集的结构。这不是一个优化规则,而是一个数据集转换
我认为它不值得一个新的优化规则
话虽如此,您为什么不做以下操作:
// check the length of the array column
val theArrayColumn = ...
val size = distance.select(size(theArrayColumn) as "size").orderBy("size").as[Int].head
val inputDF = if (size > M) {
recalculateDistance()
} else {
// we're fine
distance
}
getNNeighbors(inputDF)
如果您更详细地描述getNNeighbors
,那可能会更简单
size
是中的一个函数。这看起来与您的另一个问题非常接近:(除了一个问题被抽象到不清楚您想要什么的地步)。你最需要回答的是哪一个问题?@TheArchetypalPaul我写了这个问题,对Catalyst做了更多的研究,我得出结论,这在Catalyst中是不可能实现的。所以我提出了一个更一般的问题,两者的最终目标是一样的,我想写一个优化规则,如果新的计算是现有数据帧的子集,那么我可以返回现有数据帧的子集(或者RDD,我有两种实现)。如果可以用Catalyst实现,那就太好了,如果不行,还有没有其他方法可以在spark中声明优化规则呢。很抱歉重复地问这个问题separately@TheArchetypalPaul我的研究表明,Catalyst是spark为编写优化规则和策略提供的唯一API,并且没有其他API可用于编写更多适用于函数调用的通用规则。或者我在研究中遗漏了什么?这看起来与你的另一个问题非常接近:(除了一个问题被抽象到不清楚你想要什么的地步)。你最需要回答的是哪一个问题?@TheArchetypalPaul我写了这个问题,对Catalyst做了更多的研究,我得出结论,这在Catalyst中是不可能实现的。所以我提出了一个更一般的问题,两者的最终目标是一样的,我想写一个优化规则,如果新的计算是现有数据帧的子集,那么我可以返回现有数据帧的子集(或者RDD,我有两种实现)。如果可以用Catalyst实现,那就太好了,如果不行,还有没有其他方法可以在spark中声明优化规则呢。很抱歉重复地问这个问题separately@TheArchetypalPaul我的研究表明,Catalyst是spark为编写优化规则和策略提供的唯一API,并且没有其他API可用于编写更多适用于函数调用的通用规则。还是我在研究中遗漏了什么