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

2022-09-02 03:44:34

我已经使用方法在Hive中保存了一个远程数据库表,现在当我尝试使用CLI命令访问Hive表数据时,它会给我以下错误:saveAsTableselect * 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:

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


答案 1

问题:在查询 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)

根源:

此问题是由于 Hive 和 Spark 中使用的不同 Parquet 约定而引起的。在 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"

引用:


答案 2

我遇到了类似的错误(但在非负块中的正索引下),它来自这样一个事实,即我创建了Parquet数据,其中一些Spark数据帧类型标记为不可为空,而它们实际上是空的。

在我的情况下,我将错误解释为Spark试图从某个不可为空的类型读取数据,并偶然发现一个意外的空值。

更令人困惑的是,在阅读了 Parquet 文件后,Spark 报告所有字段都可为 null,无论它们是否为 null。但是,在我的情况下,使它们在原始 Parquet 文件中真正可为 null 解决了问题。printSchema()

现在,问题发生在“0 in block -1”的事实是可疑的:它实际上看起来好像没有找到数据,因为块-1看起来Spark甚至没有开始读取任何东西(只是一个猜测)。


推荐