背景故事
先看报错信息: mismatched input ‘-’ expecting ‘:’ 报错的意思就是说,在这个表里面,字段名中存在特殊符号“-”,无法解析报错。 这个问题会发生在CDH 的spark 中。如果不是CDH 的spark 版本的程序,可以跳过此文章。
解决方案:
不要使用CDH 版本的spark 就好了。比如我这里出现报错的时候,使用的版本是2.4.0-cdh6.1.1 那么把这个版本修改为2.4.0 就好了。
过程分析
过程早就分析完了,下面写一篇结果:
环境版本
- spark-sql_2.11
2.4.0-cdh6.1.1 - spark-hive_2.11
2.4.0-cdh6.1.1
测试数据准备
SparkSession spark = SparkSession.builder().master("local").getOrCreate();
ArrayList<Row> rows = new ArrayList<>();
for (int i = 0; i < 4; i++) {
rows.add(RowFactory.create(1, "张三", 18,"12345678"));
}
StructType schema = DataTypes.createStructType(new StructField[]{
DataTypes.createStructField("id", DataTypes.IntegerType, true),
DataTypes.createStructField("name", DataTypes.StringType, true),
DataTypes.createStructField("user-age", DataTypes.IntegerType, true),
DataTypes.createStructField("number", DataTypes.StringType, true)
});
spark.createDataFrame(rows,schema).write().orc("/Users/codes/testspark/src/orc");
spark.stop();
测试数据样例(当然: 现在将spark 的版本切换为2.4.0-cdh6.1.1 开始读取这个数据/Users/codes/testspark/src/orc 果不其然,出现如下所示的报错信息,开始调试这个程序: 断点打到ParseDriver.scala 里面的withCommand 的方法 在Idea 的debug 栏里面看到: 这个user-age 字段被解析成了三个内容:user 、- 、age .所以是这里出现了问题。 在非CDH 版本的spark 当中,这块儿变量会是什么样子呢?如下图所示: 在这个图里面,user-age 被成功解析了,并且套上了一对反引号。 那么,是什么东西造成了这样的不同呢?
核心原因:
原因是在CDH 的spark 中,有一个类org.apache.orc.TypeDescription 在解析数据schema 的过程中,不能正确识别字段中含有的特殊符号(cdh 版本的该类与开源版本相比缺失了一些解析字段名称的方法),也就不能给这些含有特殊符号的字段名称添加一对反引号。导致最后生成的。schema 信息过不去词法分析器步骤,所以报错。 具体的原因是在这表的结构信息转换成protobuf 格式的时候: 这块地方是cdh 版本的spark 调用的toString() 方法中的printToBuffer() 方法里面的详细内容: 这个是开源版本的: 这里多调用了一个printFieldName 的方法,我们开看看方法: 这里就是为了给字段名中添加反引号的地方了。 到这里,全部解释完毕了。
总结
原因找到了那么接下来的解决方案就好办了,可以对症下药。写到这里,如果各位大佬有什么更好的建议,请在下方留言:
|