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

pdkcd3nj  于 2021-06-02  发布在  Hadoop
关注(0)|答案(6)|浏览(501)

我已在配置单元中使用 saveAsTable 方法,现在当我尝试使用cli命令访问配置单元表数据时 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:

知道我做错什么了吗?

gmxoilav

gmxoilav1#

我有一个类似的错误,在我的例子中,我丢失了默认的构造函数

bksxznpy

bksxznpy2#

捕捉可能的差异的另一种方法是观察由两个源(比如hive和spark)生成的Parquet文件的模式差异。可以使用Parquet工具转储模式( brew install parquet-tools 对于macos):

λ $ parquet-tools schema /usr/local/Cellar/apache-drill/1.16.0/libexec/sample-data/nation.parquet
message root {
  required int64 N_NATIONKEY;
  required binary N_NAME (UTF8);
  required int64 N_REGIONKEY;
  required binary N_COMMENT (UTF8);
}
b4wnujal

b4wnujal3#

这里看起来像是架构不匹配的问题。如果您将模式设置为不可为null,并且创建的Dataframe没有值,spark会抛出valueerror:此字段不可为null,但没有错误。
[皮斯帕克]

from pyspark.sql.functions import * #udf, concat, col, lit, ltrim, rtrim
from pyspark.sql.types import *  

schema = ArrayType(StructType([StructField('A', IntegerType(), nullable=False)]))

# It will throw "ValueError".

df = spark.createDataFrame([[[None]],[[2]]],schema=schema) 
df.show()

但如果你使用自定义项就不是这样了。
使用相同的模式,如果使用udf进行转换,即使udf返回none,也不会抛出valueerror。它是发生数据模式不匹配的地方。
例如:

df = spark.createDataFrame([[[1]],[[2]]], schema=schema)

def throw_none():
    def _throw_none(x):
        if x[0][0] == 1:
            return [['I AM ONE']] 
        else:
            return x 
    return udf(_throw_none, schema) 

# since value col only accept intergerType, it will throw null for

# string "I AM ONE" in the first row. But spark did not throw ValueError

# error this time ! This is where data schema type mismatch happen !

df = df.select(throw_none()(col("value")).name('value'))  
df.show()


然后,下面的parquet write and read将抛出parquet.io.parquetdecodingexception错误。

df.write.parquet("tmp")
spark.read.parquet("tmp").collect()

因此,如果您使用的是自定义项,请务必小心空值,并在自定义项中返回正确的数据类型。除非没有必要,请不要在structfield中设置nullable=false。设置nullable=true将解决所有问题。

baubqpgj

baubqpgj4#

你能用avro代替Parquet地板来存放你的Hive桌吗?我遇到这个问题是因为我使用的是hive的decimal数据类型,而spark的parquet不能很好地处理decimal。如果发布表架构和一些数据示例,调试将更容易。
另一个可能的选择,来自databricks论坛,是使用double而不是decimal,但这不是我的数据的一个选项,所以我不能报告它是否有效。

gojuced7

gojuced75#

问题:在查询impyla(spark job编写的数据)中的数据时遇到以下问题

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约定造成的。在配置单元中,十进制数据类型表示为固定字节(int 32)。在spark 1.4或更高版本中,默认约定是使用十进制数据类型的标准Parquet表示法。根据基于列数据类型精度的标准parquet表示,底层表示会发生变化。
例如:decimal可用于注解以下类型:int32:for 1<=precision<=9 int64:for 1<=precision<=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"

参考文献:
语言手册类型小数位数小数位数
Spark-20937
issues@spark.apache.org

mxg2im7a

mxg2im7a6#

我也有一个类似的错误(但在非负块中的正索引处),这是因为我创建了带有一些sparkDataframe类型的parquet数据,这些类型在实际为null时被标记为不可为null。
因此,在我的例子中,我将错误解释为spark试图从某个不可为null的类型读取数据,并遇到意外的null值。
更让人困惑的是,在阅读了Parquet文件之后,spark用 printSchema() 所有字段都可以为空,不管它们是否为空。但是,在我的例子中,使它们在原始的parquet文件中真正可为null就解决了这个问题。
现在,这个问题发生在“block-1中的0”这一事实是可疑的:实际上看起来几乎没有找到数据,因为block-1看起来spark甚至没有开始读取任何内容(只是一个猜测)。

相关问题