数据存储在对象存储中时从 Spark SQL 访问 Hive 表

Posted

技术标签:

【中文标题】数据存储在对象存储中时从 Spark SQL 访问 Hive 表【英文标题】:Accessing Hive Tables from Spark SQL when Data is Stored in Object Storage 【发布时间】:2018-12-18 09:13:51 【问题描述】:

我正在使用 spark 数据帧编写器在 IBM Cloud Object Storage 中以 parquet 格式将数据写入内部配置单元表中。 所以,我的配置单元元存储在 HDP 集群中,我正在从 HDP 集群运行 spark 作业。此 spark 作业以 parquet 格式将数据写入 IBM COS。 这就是我开始 spark 会话的方式

SparkSession session = SparkSession.builder().appName("ParquetReadWrite")
                                .config("hive.metastore.uris", "<thrift_url>")
                                .config("spark.sql.sources.bucketing.enabled", true)
                                .enableHiveSupport()
                                .master("yarn").getOrCreate();
session.sparkContext().hadoopConfiguration().set("fs.cos.mpcos.iam.api.key",credentials.get(ConnectionConstants.COS_APIKEY));
session.sparkContext().hadoopConfiguration().set("fs.cos.mpcos.iam.service.id",credentials.get(ConnectionConstants.COS_SERVICE_ID));
session.sparkContext().hadoopConfiguration().set("fs.cos.mpcos.endpoint",credentials.get(ConnectionConstants.COS_ENDPOINT));

我面临的问题是,当我对数据进行分区并存储它(通过 partitionBy)时,我无法直接从 spark sql 访问数据

spark.sql("select * from partitioned_table").show

要从分区表中获取数据,我必须加载数据帧并将其注册为临时表,然后对其进行查询。 表未分区时不会出现上述问题。 写入数据的代码是这样的

dfWithSchema.orderBy(sortKey).write()
                                .partitionBy("somekey")
                                .mode("append")
                                .format("parquet")
                                .option("path",PARQUET_PATH+tableName )
                                .saveAsTable(tableName);

知道为什么直接查询方法不适用于 COS/Parquet 中的分区表吗?

【问题讨论】:

【参考方案1】:

要读取分区表(由Spark创建),您需要给出表的绝对路径,如下所示。

selected_Data=spark.read.format("parquet").option("header","false").load("hdfs/path/loc.db/partition_table")

要进一步过滤,请尝试以下方法。

selected_Data.where(col("column_name")=='col_value').show()

【讨论】:

我不想使用 spark.load api 加载数据然后查询它。当分区的 hive 表存储在 HDFS 中时,我可以直接通过 spark.sql("select statement") 查询该表。但是我将数据存储在 COS 中。如果我直接运行 spark sql 作为选择语句,它不会返回任何行【参考方案2】:

当属性 hive.metastore.try.direct.sql 在 HiveMetastore 配置上设置为 true 并且 SparkSQL 查询在非 STRING 类型的分区列上运行时,会出现此问题。

对于 Spark,建议创建分区列为 STRING 类型的表。

如果您在过滤 spark 中的 hive 分区表时收到以下错误消息。

Caused by: MetaException(message:Filtering is supported only on partition keys of type string)

使用分区列数据类型作为字符串重新创建您的 Hive 分区表,然后您将能够直接从 spark sql 访问数据。

否则,您必须指定 hdfs 位置的绝对路径才能获取数据,以防您的分区列已定义为 varchar。

selected_Data=spark.read.format("parquet").option("header","false").load("hdfs/path/loc.db/partition_table")

但是我无法理解,为什么它在分区列的 varchar 和 string 数据类型之间存在差异

【讨论】:

以上是关于数据存储在对象存储中时从 Spark SQL 访问 Hive 表的主要内容,如果未能解决你的问题,请参考以下文章

C# 如何从存储在数据库中的 OLE 对象中保存图像

当文件存储在列表或对象中时,为什么文件的上次访问时间会发生变化?

spark sql应该如何配置访问hive metastore? [复制]

12.spark sql之读写数据

在 Spark 2.1 独立集群的客户端部署模式下,RDD 或 Spark SQL 数据帧在哪里存储或持久化?

将sql查询存储在列表中时PHP内存耗尽