如何解决如何在Spark数据集中显示或操作由Kryo编码的对象?
说你有这个:
// assume we handle custom type
class MyObj(val i: Int,val j: String)
implicit val myObjEncoder = org.apache.spark.sql.Encoders.kryo[MyObj]
val ds = spark.createDataset(Seq(new MyObj(1,"a"),new MyObj(2,"b"),new MyObj(3,"c")))
做ds.show
时,我得到:
+--------------------+
| value|
+--------------------+
|[01 00 24 6C 69 6...|
|[01 00 24 6C 69 6...|
|[01 00 24 6C 69 6...|
+--------------------+
我知道这是因为内容被编码为内部Spark sql二进制表示形式。但是如何显示这样的解码内容?
+---+---+
| _1| _2|
+---+---+
| 1| a|
| 2| b|
| 3| c|
+---+---+
UPDATE1
显示内容不是最大的问题,更重要的是在处理数据集时可能会导致问题,请考虑以下示例:
// continue with the above code
val ds2 = spark.createDataset(Seq(new MyObj(2,new MyObj(6,new MyObj(5,"c")))
ds.joinWith(ds2,ds("i") === ds2("i"),"inner")
// this gives a Runtime error: org.apache.spark.sql.AnalysisException: Cannot resolve column name "i" among (value);
这是否意味着kryo
编码类型不能方便地执行类似joinWith
的操作?然后我们如何处理Dataset
上的自定义类型?
解决方法
以下内容对我有用,但似乎使用高级API进行低级(反序列化)工作。
这并不是说应该这样做,而是表明这是可能的。
我不知道为什么KryoDeserializer不将字节反序列化为字节来自的对象。就是这样。
您的类定义和我的类之间的主要区别是case
,让我使用以下技巧。再说一次,不知道到底为什么能做到这一点。
scala> println(spark.version)
3.0.1
// Note that case keyword
case class MyObj(val i: Int,val j: String)
import org.apache.spark.sql.Encoders
implicit val myObjEncoder = Encoders.kryo[MyObj]
// myObjEncoder: org.apache.spark.sql.Encoder[MyObj] = class[value[0]: binary]
val ds = (Seq(new MyObj(1,"a"),new MyObj(2,"b"),new MyObj(3,"c"))).toDS
// the Kryo deserializer gives bytes
scala> ds.printSchema
root
|-- value: binary (nullable = true)
scala> :type sc
org.apache.spark.SparkContext
// Let's deserialize the bytes into an object
import org.apache.spark.serializer.KryoSerializer
val ks = new KryoSerializer(sc.getConf)
// that begs for a generic UDF
val deserMyObj = udf { value: Array[Byte] =>
import java.nio.ByteBuffer
ks.newInstance.deserialize(ByteBuffer.wrap(value)).asInstanceOf[MyObj] }
val solution = ds.select(deserMyObj('value) as "result").select($"result.*")
scala> solution.show
+---+---+
| i| j|
+---+---+
| 1| a|
| 2| b|
| 3| c|
+---+---+
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。