我创建了一个从UDAF派生的类,我的类型为bufferSchema。它编译并提交,不幸的是在运行它时抛出CompileException。在日志中,在生成的代码中找到以下行:
arrayWriter1.write(index1, element1);
这个element1是我自己的类,当然spark没有这种签名的方法。
以下是我的代码:
class AggregateLinkResponse extends UserDefinedAggregateFunction {
override def inputSchema: StructType = StructType(
// the input fields definition
::Nil
)
override def bufferSchema: StructType = StructType(
StructField("xxx", MapType(IntegerType, ObjectType(classOf[MyOwnClass])))::Nil
)
override def dataType: DataType = StringType
override def deterministic: Boolean = true
override def initialize(buffer: MutableAggregationBuffer): Unit = {
buffer(0) = Map[Int, MyOwnClass]()
}
override def update(buffer: MutableAggregationBuffer, input: Row): Unit = {
val responses : Map[Int, MyOwnClass] = buffer.getAs[Map[Int, MyOwnClass]](0)
// Get the input field values
// The logic to merge to buffer
buffer(0) = responses
}
override def merge(buffer1: MutableAggregationBuffer, buffer2: Row): Unit = {
val response1 : Map[Int, MyOwnClass] = buffer1.getAs[Map[Int, MyOwnClass]](0)
val response2 : Map[Int, MyOwnClass] = buffer2.getAs[Map[Int, MyOwnClass]](0)
// the logic to merge
buffer1(0) = response1
}
override def evaluate(buffer: Row): Any = {
new Gson().toJson(buffer.getAs[Map[Int, MyOwnClass]](0))
}
}
我的问题是:
如果不允许,我知道两个选择:
a。我可以将缓冲区对象序列化为字节或json,然后每次将其反序列化。
b。使用预定义的Spark类型(包括几种ArrayType)来定义复杂的bufferSchema。
哪个选项具有更好的性能,a或b?中间对象中数组的长度会改变,并且会越来越长。我从人们那里听说每次都复制ArrayType。性能损失大吗?