Orc格式文件的元数据保存在文件中。当修改了MetaStore中hive表字段类型之后,Spark任务会抛出ClassCastException,但往往很难定位具体是哪个字段的数据存在问题。
1 背景
orc表通常在用户修改字段类型之后发生ClassCastException。异常如下:
1 | Error: java.io.IOException: java.io.IOException: java.lang.ClassCastException: org.apache.hadoop.io.IntWritable cannot be cast to org.apache.hadoop.io.Text |
如果在发生此类异常时,日志中打印出对应的字段,这样会更直观排查出是因为修改元数据导致的异常,而不是脏数据引起的异常。
异常复现demo:
1 | -- 测试数据准备 |
2 源码修复
修复思路:在org.apache.spark.sql.hive.HadoopTableReader#fillObject方法中,Spark发生类型转换异常时,将对应的字段信息输出到异常日志中,方便后续快速准确定位是由于哪个字段的变化引起的异常。
修复前:
1 | var i = 0 |
修复后:
1 | var i = 0 |
测试效果:
1 | [xiepengjie@bigdata-client01 ~/spark-2.4.3/bin]$ spark-sql --queue root.xiepengjie_offline |
在tracking uri日志中,明确告诉了发生异常的字段是c1:
20/04/09 17:22:05 ERROR hive.HadoopTableReader: Exception thrown in field
1 | 20/04/09 17:22:05 INFO executor.CoarseGrainedExecutorBackend: Got assigned task 4 |
3 总结
在MetaStore服务中,分区元数据和表的元数据是独立存储的,换言之,一个表的不同分区可以拥有不同的元数据信息。举个例子:
1 | -- 对于表 t1 有字段 c1 int,c2 string ; 其分区dt='2020-01-01'的字段可以是 c1 string, c2 string, c3 string |
hive查询正常的原因:hive引擎在查询时,会获取对应分区的元数据信息,因此不会出现类型异常;
spark查询异常的原因:spark在查询时,并没有获取对应分区的元数据信息,二是获取表的元数据信息(此时表的字段元数据和分区的字段元数据不同),因此出现了类型转换异常的错误。
该优化修复,已经提交了pr,贡献给了社区。
本文链接: https://stefanxiepj.github.io/archives/bf0645eb.html
版权声明: 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。转载请注明出处!
![知识共享许可协议](https://i.creativecommons.org/l/by-nc-sa/4.0/88x31.png)