当数据存储在对象存储器中时从sparksql访问配置单元表

e1xvtsh3  于 2021-06-27  发布在  Hive
关注(0)|答案(2)|浏览(402)

我正在使用spark dataframe writer以parquet格式在ibmcloud对象存储中写入内部配置单元表中的数据。所以,我的配置单元元存储在hdp集群中,我正在hdp集群中运行spark作业。这个spark作业以parquet格式将数据写入ibmcos。我就是这样开始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)时,我无法直接从sparksql访问数据

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

为了从分区表中获取数据,我必须加载dataframe并将其注册为临时表,然后查询它。如果表未分区,则不会出现上述问题。写数据的代码如下

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

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

bd1hkmkf

bd1hkmkf1#

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

js5cn81o2#

当hivemetastore配置上的属性hive.metastore.try.direct.sql设置为true,并且在非字符串类型的分区列上运行sparksql查询时,会发生此问题。
对于spark,建议使用字符串类型的分区列创建表。
如果在spark中筛选配置单元分区表时出现以下错误消息。

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

重新创建分区列数据类型为string的hive分区表,这样就可以直接从sparksql访问数据。
否则,如果分区列被定义为varchar,则必须指定hdfs位置的绝对路径才能获取数据。

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

但是我不明白为什么分区列要区分varchar和string数据类型

相关问题