问题:在查询 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"
引用: