Chr*_*son 1 java apache-spark parquet apache-spark-sql
Spark解释木条柱的方式存在一些问题.
我有一个带有确认模式的Oracle源代码(df.schema()方法):
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)
Run Code Online (Sandbox Code Playgroud)
然后保存为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));
}
Run Code Online (Sandbox Code Playgroud)
然后,我的应用程序使用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>'
Run Code Online (Sandbox Code Playgroud)
我的问题是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]
Run Code Online (Sandbox Code Playgroud)
我怎么知道何时用十进制字段替换BIGINT?
镶木地板消息类型已记录但无法访问?
两个十进制字段转换为fixed_len_byte_array(16),LM_PERSON_ID转换为int64
我能想到的唯一解决方案是创建表,测试它是否返回,如果没有丢弃,则将十进制字段逐个替换为BIGINT,每次测试.
我在这里错过了什么?我可以为镶木地板文件强制执行十进制模式吗?
由Spark编写的非常相似的SPARK-20297镶木地板十进制(12,2)是Hive不可读的,Impala最近(20/Apr/17 01:59)被解决为非问题.
重点是使用false属性并以遗留格式编写镶木地板元数据(我在配置下的官方文档中没有看到这种情况,并报告为SPARK-20937的改进).
启用spark.sql.parquet.writeLegacyFormat时,Hive和Impala可以读取Spark编写的数据.
它遵循较新的标准 - https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#decimal,我错过了文档.不会是Impala或Hive中的错误吗?
int32/int64选项存在于十进制规范的原始版本中,它们没有被广泛实现:https://github.com/Parquet/parquet-format/commit/b2836e591da8216cfca47075baee2c9a7b0b9289.所以它不是一个新的/旧版本的东西,它只是许多系统没有实现的替代表示.
这个SPARK-10400也可以是一个非常有用的阅读(关于spark.sql.parquet.writeLegacyFormat财产的历史):
我们在SPARK-6777中实现Parquet向后兼容性规则时引入了SQL选项"spark.sql.parquet.followParquetFormatSpec".它表明我们是否应该使用Spark 1.4和之前版本采用的传统Parquet格式或者镶木地板格式规范中定义的标准格式.但是,这个选项的名称有点令人困惑,因为我们不应该遵循规范,这不是超级直观的.很高兴将它重命名为"spark.sql.parquet.writeLegacyFormat"并反转其默认值(它们具有相反的含义).请注意,此选项不是"public"(isPublic为false).