为什么在Spark SQL&写入之后,&t Impala可以读取镶木地板文件?

Spark解释镶木地板柱子的方式有一些问题。

我有一个具有确认架构(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().parket()方法,并带有相应的消息类型(由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,则表将仅读取拼图文件。

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]

如何知道何时用Decimal字段替换BIGINT?

拼接消息类型已记录,但无法访问?

两个十进制字段转换为FIXED_LEN_BYTE_ARRAY(16),LM_PERSON_ID转换为int64

我能想到的唯一解决办法是创建表,测试它是否返回,如果不返回,则逐个删除小数字段并将其替换为BIGINT,每次都进行测试。

我在这里错过了什么?我可以强制拼图文件使用十进制架构吗?


解决方案

来自ApacheSpark官方文档中Parquet Files的Configuration部分:

spark.sql.parquet.writeLegacyFormat(默认:false)

如果为True,则数据将以Spark 1.4及更早版本的方式写入。例如,十进制值将以ApacheParquet的固定长度字节数组格式写入,其他系统(如ApacheHave和ApacheImpala)也使用这种格式。如果为False,则将使用拼图中较新的格式。例如,小数将以基于整型的格式写入。如果拼图输出用于不支持此较新格式的系统,请设置为TRUE。

公文更新前的答复

非常类似的SPARK-20297 Parquet Decimal(12,2) written by Spark is unreadable by Hive and Impala最近(20/Apr/17 01:59)被解决为不是问题。

主要是使用spark.sql.parquet.writeLegacyFormat属性并以遗留格式编写拼图元数据(我在Configuration下的官方文档中没有描述,并且在SPARK-20937中报告为改进)。

启用spak.sql.parquet.WriteLegacyFormat时,Spark写入的数据可由配置单元和Impala读取。

它确实遵循较新的标准-https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#decimal,我错过了文档。 那不就是黑斑羚或蜂巢里的虫子了吗?

int32/int64选项出现在DECIMAL规范的原始版本中,只是它们没有被广泛实现:https://github.com/Parquet/parquet-format/commit/b2836e591da8216cfca47075baee2c9a7b0b9289。因此,它不是新/旧版本的东西,它只是许多系统没有实现的替代表示法。

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

我们在致力于实现SPARK-6777中的向后兼容规则时,引入了SQL选项"spk.sql.parquet.postParquetFormatSpec"。它指示我们是应该使用Spark 1.4及更早版本采用的传统拼图格式,还是应该使用拼图格式规范中定义的标准格式。然而,这个选项的名称有点令人困惑,因为它并不是我们不应该遵循规范的超直观的原因。最好将其重命名为"spk.sql.parquet.WriteLegacyFormat",并反转其缺省值(它们具有相反的含义)。请注意,此选项不是"Public"(isPublic为False)。

相关文章