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

时间:2018-12-18 09:13:52

标签: apache-spark hive object-storage

我正在使用spark数据帧写入器以镶木地板格式将内部蜂巢表中的数据写入IBM Cloud Object Storage。 因此,我的配置单元metastore在HDP集群中,并且我正在从HDP集群运行spark作业。此spark作业以镶木地板格式将数据写入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中的分区表?

2 个答案:

答案 0 :(得分:0)

要读取分区表(由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()

答案 1 :(得分:0)

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

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

如果在Spark中过滤配置单元分区表时出现以下错误消息。

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

使用分区列数据类型作为字符串重新创建配置单元分区表,然后您就可以直接从spark sql访问数据。

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

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

但是我不明白,为什么要区分分区列的varchar和字符串数据类型