为什么 Impala 在 Spark SQL 写入后无法读取镶木地板文件?



在Spark正在解释Parquet的列的方式上有一些问题。

我有一个带有确认架构(df.schema((方法(的Oracle源:

root
  |-- LM_PERSON_ID: decimal(15,0) (nullable = true)
  |-- LM_BIRTHDATE: timestamp (nullable = true)
  |-- LM_COMM_METHOD: string (nullable = true)
  |-- LM_SOURCE_IND: string (nullable = true)
  |-- DATASET_ID: decimal(38,0) (nullable = true)
  |-- RECORD_ID: decimal(38,0) (nullable = true)

然后将其保存为parquet -df.write((。parquet((方法 - 带有相应的消息类型(由Spark确定(:

  message spark_schema {
    optional int64 LM_PERSON_ID (DECIMAL(15,0));
    optional int96 LM_BIRTHDATE;
    optional binary LM_COMM_METHOD (UTF8);
    optional binary LM_SOURCE_IND (UTF8);
    optional fixed_len_byte_array(16) DATASET_ID (DECIMAL(38,0));
    optional fixed_len_byte_array(16) RECORD_ID (DECIMAL(38,0));
}

我的应用程序然后使用hashmap进行类型转换生成表DDL,例如:

CREATE EXTERNAL TABLE IF NOT EXISTS 
ELM_PS_LM_PERSON (
LM_PERSON_ID DECIMAL(15,0)
,LM_BIRTHDATE TIMESTAMP
,LM_COMM_METHOD STRING
,LM_SOURCE_IND STRING
,DATASET_ID DECIMAL(38,0)
,RECORD_ID DECIMAL(38,0)
) PARTITIONED BY (edi_business_day STRING) STORED AS PARQUET LOCATION '<PATH>'

我的问题是,该表将无法由Impala读取,因为它不会接受lm_person_id作为十进制字段。该表仅在将此列设置为bigint时才读取镶木quet文件。

Query 8d437faf6323f0bb:b7ba295d028c8fbe: 0% Complete (0 out of 1)
File 'hdfs:dev/ELM/ELM_PS_LM_PERSON/part-00000-fcdbd3a5-9c93-490e-a124-c2a327a17a17.snappy.parquet' has an incompatible Parquet schema for column 'rbdshid1.elm_ps_lm_person_2.lm_person_id'. 
Column type: DOUBLE, Parquet schema:
optional int64 LM_PERSON_ID [i:0 d:1 r:0]

我怎么知道何时将小数球替换为bigint?

镶木木消息类型已记录但无法访问?

将两个小数点字段转换为fixed_len_byte_array(16(,lm_person_id转换为int64

我唯一能想到的分辨率是创建表,测试它是否返回,如果不掉落,并替换了十进制的小数字段,则每次测试。

我在这里想念什么?我可以为十进制的镶木式文件执行模式吗?

来自Apache Spark的正式文档中的Parquet文件的配置部分:

spark.sql.parquet.writelegacyformat (默认值: false(

如果是真的,数据将以SPARK 1.4和更早的方式编写。例如,十进制值将写在Apache Parquet的固定长度阵列格式中,其他系统(例如Apache Hive和Apache Impala(使用它们。如果是错误的,则将使用Parquet中的较新格式。例如,小数将以基于INT的格式编写。如果用于与不支持此较新格式的系统一起使用,请设置为true。

在官方文档更新之前给出的答案

Spark非常相似的Spark-20297 Parquet十进制(12,2(是Hive and Impala不可读取的(20/Apr/17 01:59(,这不是一个问题。

要点是使用 spark.sql.parquet.writeLegacyFormat属性并以遗留格式编写镶木元(我看不到官方文档中的官方文档中描述的,并报告为Spark-20937的改进(。

Spark编写的数据是由Hive和Impala读取的Spark.sql.parquet.writelegacyformat。

它确实遵循较新的标准-https://github.com/apache/parquet-format/blob/master/master/logicaltypes.md#decimal,我错过了文档。 在Impala或Hive中会不是错误吗?

INT32/INT64选项以十进制规格的原始版本存在,它们并未得到广泛实现:https://github.com/parquet/parquet/parquet/parquet-format/commit/commit/b2836e591da8216cfca470755baeee2c9a7b0b0b9289。因此,它不是新版本的东西,它只是许多系统没有实现的替代表示。

此SPARK-10400也可能是一本非常有用的阅读(关于spark.sql.parquet.writeLegacyFormat属性的历史(:

我们在Spark-6777中实施Parquet向后兼容规则时,我们引入了SQL选项" Spark.sql.parquet.followparquetformatspec"。它表明我们是否应该使用Spark 1.4和先前版本采用的旧版镶木格式,或者是否应该使用Parquet-Format规范中定义的标准格式。但是,此选项的名称有些令人困惑,因为这不是我们不应该遵循规格的超级直觉。将其重命名为" spark.sql.parquet.writelegacyformat"并倒转其默认值(它们具有相反的含义(会很不错。请注意,此选项不是" public"(iSpublic是false(。

相关内容

最新更新