我正在尝试在组状态下进行排序的集合,并且从催化剂中得到一个错误,我认为这是该集合的默认实例创建。
下面是演示错误的简化管道:
package com.example
import org.apache.spark.sql.SparkSession
import org.apache.spark.sql.functions._
import org.apache.spark.sql.streaming.{GroupState, GroupStateTimeout, OutputMode, Trigger}
import scala.collection.immutable.TreeMap
case class Event
(
key: String
)
case class KeyState
(
prop: TreeMap[Long, String]
)
object CatalystIssue {
def updateState(k: String, vs: Iterator[Event],
state: GroupState[KeyState]) : Iterator[Event] = vs
def main(args: Array[String]) {
val spark = SparkSession.builder()
.master("local[*]")
.appName("CatalystIssue")
.getOrCreate()
import spark.implicits._
val df = spark.readStream.format("rate")
.load()
.select(lit("a").as("key"))
.as[Event]
.groupByKey(_.key)
.flatMapGroupsWithState(OutputMode.Append(),
GroupStateTimeout.NoTimeout())(updateState)
val query = df.writeStream.format("console")
.trigger(Trigger.ProcessingTime("30 seconds")).start()
query.awaitTermination()
}
}
哪个会产生错误:
ERROR org.apache.spark.sql.catalyst.expressions.codegen.CodeGenerator - failed to compile: org.codehaus.commons.compiler.CompileException: File 'generated.java', Line 53, Column 106: No applicable constructor/method found for zero actual parameters; candidates are: "public scala.collection.mutable.Builder scala.collection.generic.SortedMapFactory.newBuilder(scala.math.Ordering)"
这可能是因为dataframe attribute type不支持Sorted Maps,尽管这不是我的意图,并且我本以为KeyState会不透明,因为您实际上并不像dataframe属性那样访问它
虽然不是很吸引人,但是一个选择可能是将排序后的集合序列化为一个字节数组,该数组是KeyState的属性。即
case class KeyState
(
prop: Array[Byte]
)
如果使用Java序列化,是否可以保留TreeMap的内部树结构,以便至少不必重建该树结构?是否有其他替代序列化技术可以保留结构?
能够将某些排序的集合保持在组状态似乎很有用,尤其是因为计算应该主要在内存中进行。火花的工作方式是否有某种本质上使其不可行的方法?