parquet.io.ParquetDecodingException:无法读取文件中块-1中0的值

ser*_*com 11 java hadoop hive apache-spark

我在Hive中使用saveAsTable方法保存了一个远程数据库表,现在当我尝试使用CLI命令访问Hive表数据时select * from table_name,它给出了以下错误:

2016-06-15 10:49:36,866 WARN  [HiveServer2-Handler-Pool: Thread-96]:
thrift.ThriftCLIService (ThriftCLIService.java:FetchResults(681)) -
Error fetching results: org.apache.hive.service.cli.HiveSQLException:
java.io.IOException: parquet.io.ParquetDecodingException: Can not read
value at 0 in block -1 in file hdfs:
Run Code Online (Sandbox Code Playgroud)

知道我在这里做错了什么吗?

小智 5

问题: 在impyla中查询数据时遇到以下问题(由spark作业写入的数据)

ERROR: Error while processing statement: FAILED: Execution Error, return code 2 from org.apache.hadoop.hive.ql.exec.tez.TezTask. Vertex failed, vertexName=Map 1, vertexId=vertex_1521667682013_4868_1_00, diagnostics=[Task failed, taskId=task_1521667682013_4868_1_00_000082, diagnostics=[TaskAttempt 0 failed, info=[Error: Failure while running task:java.lang.RuntimeException: java.lang.RuntimeException: java.io.IOException: org.apache.parquet.io.ParquetDecodingException: Can not read value at 0 in block -1 in file hdfs://shastina/sys/datalake_dev/venmo/data/managed_zone/integration/ACCOUNT_20180305/part-r-00082-bc0c080c-4080-4f6b-9b94-f5bafb5234db.snappy.parquet
    at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.initializeAndRunProcessor(TezProcessor.java:173)
    at org.apache.hadoop.hive.ql.exec.tez.TezProcessor.run(TezProcessor.java:139)
    at org.apache.tez.runtime.LogicalIOProcessorRuntimeTask.run(LogicalIOProcessorRuntimeTask.java:347)
    at org.apache.tez.runtime.task.TezTaskRunner$TaskRunnerCallable$1.run(TezTaskRunner.java:194)
    at org.apache.tez.runtime.task.TezTaskRunner$TaskRunnerCallable$1.run(TezTaskRunner.java:185)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:422)
    at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1724)
    at org.apache.tez.runtime.task.TezTaskRunner$TaskRunnerCallable.callInternal(TezTaskRunner.java:185)
    at org.apache.tez.runtime.task.TezTaskRunner$TaskRunnerCallable.callInternal(TezTaskRunner.java:181)
    at org.apache.tez.common.CallableWithNdc.call(CallableWithNdc.java:36)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:745)
Run Code Online (Sandbox Code Playgroud)

根本原因:

由于在Hive和Spark中使用不同的实木复合地板约定而导致此问题。在Hive中,十进制数据类型表示为固定字节(INT 32)。在Spark 1.4或更高版本中,默认约定是对十进制数据类型使用标准Parquet表示形式。根据基于列数据类型的精度的标准Parquet表示形式,基础表示形式也会发生变化。
例如:DECIMAL可用于注释以下类型:int32:表示1 <=精度<= 9 int64:表示1 <=精度<= 18;精度<10将产生警告

因此,仅在使用不同Parquet约定中具有不同表示形式的数据类型时,才会发生此问题。如果数据类型为DECIMAL(10,3),则两种约定都将其表示为INT32,因此我们不会遇到问题。如果您不了解数据类型的内部表示,可以安全地使用读取时进行写入的相同约定。使用Hive,您没有选择Parquet约定的灵活性。但是有了Spark,您就可以了。

解决方案: Spark用来写入Parquet数据的约定是可配置的。这由属性spark.sql.parquet.writeLegacyFormat确定。默认值为false。如果设置为“ true”,Spark将使用与Hive相同的约定来写入Parquet数据。这将有助于解决问题。

--conf "spark.sql.parquet.writeLegacyFormat=true"
Run Code Online (Sandbox Code Playgroud)

参考文献:


Emm*_*day 0

您可以使用 Avro 而不是 Parquet 来存储 Hive 表吗?我遇到这个问题是因为我使用了 Hive 的 Decimal 数据类型,而 Spark 中的 Parquet 与 Decimal 配合得不好。如果您发布表架构和一些数据示例,调试会更容易。

来自 DataBricks Forum 的另一个可能的选择是使用 Double 而不是 Decimal,但这不是我的数据的选项,因此我无法报告它是否有效。