Spark如何获取Hive外部表指定分区的存储文件路径
运行时获取Hive外部表指定分区存储路径的解决方法
问题根因
你之前使用的SQL拼接方案报错,是因为timestamp类型的分区值直接调用toString后,没有加引号且格式不符合Spark SQL语法规范,导致语法解析失败。
推荐方案:使用Spark内置Catalog API(与saveAsTable同源逻辑)
该方案是spark.write.saveAsTable写入分区时生成、存储路径元数据调用的同款底层接口,无需拼接SQL,天然兼容所有分区字段类型,不会出现类型格式报错:
import org.apache.spark.sql.catalyst.TableIdentifier import org.apache.hadoop.fs.Path // 构造分区筛选条件,支持任意类型的分区值 val partitionSpec = Map(partitionBy -> partitionValue) // 解析库名和表名,若表没有指定库可省略database参数 val tableParts = tableName.split("\\.") val (dbName, pureTableName) = if (tableParts.length == 2) (tableParts(0), tableParts(1)) else ("default", tableParts(0)) // 调用外部Catalog接口直接获取分区元数据 val partition = spark.sharedState.externalCatalog.getPartition(dbName, pureTableName, partitionSpec) // 直接获取分区对应的存储路径 val partitionPath: Path = partition.location
拿到路径后如果需要删除底层数据,可直接通过Hadoop FileSystem API操作对应路径,再执行
ALTER TABLE DROP PARTITION同步删除元数据即可。
备用方案:修复原有SQL拼接逻辑
如果要继续使用DESCRIBE PARTITION的SQL方案,需要针对不同类型的分区值做语法兼容处理:
// 针对不同类型的分区值做格式化转义 val formattedValue = partitionValue match { case ts: java.sql.Timestamp => s"'${ts.toString}'" case str: String => s"'${str.replace("'", "\\'")}'" case other => other.toString } // 执行查询 val descResult = spark.sql(s"DESCRIBE $tableName PARTITION ($partitionBy = $formattedValue)") // 从结果中提取Location字段对应的值即为存储路径 val partitionPath = descResult.filter("col_name = 'Location'").head().getString(1)
内容的提问来源于stack exchange,提问作者kmes40505
相关产品推荐
相关产品推荐

