我正在使用一个SerDe,它根据基础数据集以各种方式处理Thrift对象条目。它本质上是一个美化的Hive Struct,它在运行时处理基本数据集,而不是将结果存储在表中。最近,我已经将集群从Hive 0.7.1升级到Hive 0.10.0(带有CDH3 - > CDH4.3.0),并且SerDe不再懒惰地处理数据,而是似乎正在处理定义的每个字段。
我已经挖掘了Hive的代码,并查看了我们的数据如何被反序列化以了解它如何确定它想要处理哪些字段,但遗憾的是它似乎只是因为我们的ObjectInspector正在处理所有列返回我们自定义对象的所有字段,我似乎无法弄清楚如何控制正在处理的字段。
我可以操作Hive的哪些部分来更改正在处理的字段?有没有办法可以检测查询中使用的字段,以便在对象的内部状态中禁用函数?
编辑:我意识到包含一个堆栈跟踪以显示正在调用处理数据的特定函数的位置是有用的,因为它是一个被检查的字段。
我已将自定义类名替换为其角色的描述性名称。
2013-10-08 17:02:45,198 INFO CustomStructFunction: Stack trace: java.lang.Throwable
at CustomStructFunction.init(CustomStructFunction.java:490)
at CustomStructFunctionBase.process(CustomStructFunctionBase.java:27)
at CustomStructObject.callImplementor(CustomStructObject.java:332)
at CustomStructField.callImplementor(CustomStructField.java:161)
at CustomStructField.getValue(CustomStructField.java:131)
at CustomStructObjectInspector.getStructFieldData(CustomStructObjectInspector.java:46)
at org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorConverters$StructConverter.convert(ObjectInspectorConverters.java:298)
at org.apache.hadoop.hive.ql.exec.MapOperator.process(MapOperator.java:630)
at org.apache.hadoop.hive.ql.exec.ExecMapper.map(ExecMapper.java:141)
at org.apache.hadoop.mapred.MapRunner.run(MapRunner.java:50)
at org.apache.hadoop.mapred.MapTask.runOldMapper(MapTask.java:417)
at org.apache.hadoop.mapred.MapTask.run(MapTask.java:332)
at org.apache.hadoop.mapred.Child$4.run(Child.java:268)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:396)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1408)
at org.apache.hadoop.mapred.Child.main(Child.java:262)
答案 0 :(得分:0)
事实证明,每次我们要求获取它时,我们的自定义对象都会返回一个新的ObjectInspector。这导致Hive认为自定义结构的输入格式与导出的格式是分开的,这会触发Hive将数据转换为基础结构对象,这实质上意味着处理每个字段。
不是每次在我们的基本自定义结构定义中返回一个新的ObjectInspector,而是将它留给扩展类来定义一个以null开头的静态ObjectInspector。然后父类调用方法“getInnerObjectInspector”,如果它变为null,则使用类似的set方法和新实例设置它。