当前位置: 首页 > 面试题库 >

为什么在Spark SQL写完之后Impala无法读取实木复合地板文件?

葛炯
2023-03-14
问题内容

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)

然后将其另存为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,则该表仅读取镶木地板文件。

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

我能想到的唯一解决方案是创建表,测试它是否返回(如果未返回),然后将小数字段逐一替换为BIGINT,每次测试。

我在这里想念什么?我可以为镶木地板文件强制使用十进制格式吗?


问题答案:

在Apache Spark官方文档中的Parquet Files的“ 配置”部分中:

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

如果为true,则将以Spark 1.4及更低版本写入数据。例如,十进制值将以Apache
Parquet的固定长度字节数组格式编写,其他系统(例如Apache Hive和Apache
Impala)将使用该格式。如果为false,将使用Parquet中较新的格式。例如,小数将以基于int的格式编写。如果Parquet输出打算用于不支持这种较新格式的系统,请设置为true。

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

Hive无法读取由Spark编写的非常相似的SPARK-20297
Parquet
Decimal(12,2),并且Impala
最近(20
/ Apr / 17 01:59)解决为“不是问题”。

主要要点是使用spark.sql.parquet.writeLegacyFormat属性并以旧格式编写实木复合地板元数据(我在官方文档的“
配置”下没有看到此描述,而在SPARK-20937中对此进行了报告)。

启用spark.sql.parquet.writeLegacyFormat时,Hive和Impala可以读取Spark写入的数据。

它确实遵循更新的标准-https://github.com/apache/parquet-
format/blob/master/LogicalTypes.md#decimal,但我错过了文档。难道不是Impala或Hive中的bug?

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格式,还是使用Parquet格式规范中定义的标准格式。但是,此选项的名称有些令人困惑,因为我们不应该遵循该规范并不是超级直观。最好将其重命名为“
spark.sql.parquet.writeLegacyFormat”并反转其默认值(它们的含义相反)。请注意,此选项不是“
public”(isPublic为false)。



 类似资料:
  • 我正在从Impala迁移到SparkSQL,使用以下代码读取一个表: 我如何调用上面的SparkSQL,这样它就可以返回这样的东西:

  • 问题内容: 我需要从AWS S3读取实木复合地板数据。如果我为此使用aws sdk,则可以得到如下输入流: 但是apache木地板阅读器仅使用本地文件,如下所示: 所以我不知道如何解析实木复合地板文件的输入流。例如,对于csv文件,存在使用inputstream的CSVParser。 我知道使用Spark实现此目标的解决方案。像这样: 但是我不能使用火花。 谁能告诉我从s3读取镶木地板数据的任何解

  • 问题内容: 我正在寻找使用python从s3的多个分区目录中读取数据的方法。 data_folder / serial_number = 1 / cur_date = 20-12-2012 / abcdsd0324324.snappy.parquet data_folder / serial_number = 2 / cur_date = 27-12-2012 / asdsdfsd0324324.

  • 请帮帮我,我是一个完全的傻瓜,当涉及到火花和Haddop一般。我的代码如下所示: 我的Spark集群作为一个集群部署在10.1.50.165中,运行RHEL6,当我运行这段简单的代码时,在尝试读取json文件时,我遇到了如下异常:

  • 我无法使用镶木地板文件将列的类型从更改为。 使用: 改变表DATABASE.TABLE改变COL INT(从字符串到int) 或 < code >更改表数据库。表格更改列列字符串(从int到string) 读取数据时产生错误: 文件x的“db.table.col”列具有不兼容的拼花架构。列类型:INT,拼花模式:可选byte_array col[i:1 d:1 r:0] 读了这个留档,我明白: T

  • 问题内容: 我有一种使用(1.4.4),(0.4.1)和(0.20.3)实现此目的的方法。 首先,我可以像这样在本地读取单个实木复合地板文件: 我还可以像这样在本地读取实木复合地板文件的目录: 两者都像魅力。现在,我想使用存储在S3存储桶中的文件远程实现相同的目的。我希望这样的事情行得通: 但这不是: 在彻底阅读了pyarrow的文档之后,目前看来这是不可能的。因此,我提出了以下解决方案: 从S3