我正在尝试使用SparkSql配置单元上下文读取配置单元表。但是,当我提交作业时,我会收到以下错误:
Exception in thread "main" java.lang.RuntimeException: Unsupported parquet datatype optional fixed_len_byte_array(11) amount (DECIMAL(24,7))
at scala.sys.package$.error(package.scala:27)
at org.apache.spark.sql.parquet.ParquetTypesConverter$.toPrimitiveDataType(ParquetTypes.scala:77)
at org.apache.spark.sql.parquet.ParquetTypesConverter$.toDataType(ParquetTypes.scala:131)
at org.apache.spark.sql.parquet.ParquetTypesConverter$$anonfun$convertToAttributes$1.apply(ParquetTypes.scala:383)
at org.apache.spark.sql.parquet.ParquetTypesConverter$$anonfun$convertToAttributes$1.apply(ParquetTypes.scala:380)
列类型为DECIMAL(24,7(。我已经用HiveQL更改了列类型,但它不起作用。此外,我还尝试在sparksql中转换为另一种Decimal类型,如下所示:
val results = hiveContext.sql("SELECT cast(amount as DECIMAL(18,7)), number FROM dmp_wr.test")
但是,我也犯了同样的错误。我的代码是这样的:
def main(args: Array[String]) {
val conf: SparkConf = new SparkConf().setAppName("TColumnModify")
val sc: SparkContext = new SparkContext(conf)
val vectorAcc = sc.accumulator(new MyVector())(VectorAccumulator)
val hiveContext = new org.apache.spark.sql.hive.HiveContext(sc)
val results = hiveContext.sql("SELECT amount, number FROM dmp_wr.test")
我该如何解决这个问题?感谢您的回复。
Edit1:我找到了引发异常的Spark源代码行。看起来像
if(originalType == ParquetOriginalType.DECIMAL && decimalInfo.getPrecision <= 18)
所以,我创建了一个新的表,它有DECIMAL(18,7(类型的列,我的代码按预期工作。我删除表并创建一个新表,该表的列在DECIMAL(24,7(中,之后我更改了列类型alter table qwe change amount amount decimal(18,7)
和我可以看到它被改为DECIMAL(18,7(,但Spark不接受更改。它仍然将列类型读取为DECIMAL(24,7(,并给出相同的错误。主要原因是什么?
alter table qwe change amount amount decimal(18,7)
单元中的"更改表格"命令不会触及存储在单元中的实际数据。它只更改配置单元Metastore中的元数据。这与普通数据库(如MySQL(中的"altertable"命令非常不同。
当Spark从Parquet文件中读取数据时,它会尝试使用实际Parquet中的元数据来反序列化数据,这仍然会给它DECIMAL(24,7(。
您的问题有两种解决方案:1.试用一个新版本的Spark-从trunk构建。看见https://issues.apache.org/jira/browse/SPARK-6777这完全改变了这部分代码(不过只会出现在Spark 1.5中(,所以希望您不会再看到同样的问题。
- 手动转换表中的数据。您可以使用配置单元查询(如"INSERT OVERWRITE TABLE new_TABLE SELECT*from old_TABLE"(来执行此操作