Spark读取Hive CLI与Spark创建的Hive表的逻辑计划差异及识别方法
Spark Event Listener开发中的表读取行为差异解析
问题背景
开发Spark Event Listener时遇到两类场景的行为差异:
- 场景1:Spark API创建表
通过Spark的saveAsTable创建company.EMPLOYEE表,使用Spark读取时生成的LogicalPlan会直接引用完整的CatalogTable对象,包含详细元数据:CatalogTable( Database: company Table: EMPLOYEE Created Time: Mon Jun 01 02:59:11 GMT 2022 Last Access: UNKNOWN Created By: Spark Type: MANAGED Provider: orc ) - 场景2:Hive CLI创建表
通过Hive CLI创建同名company.EMPLOYEE表,使用Spark读取时生成的LogicalPlan仅显示HDFS路径,未引用CatalogTable对象,但该表可在Hive元数据中正常访问。
附Spark写入表的Java代码:
SparkSession spark = SparkSession .builder() .appName("HiveZipCodePipeline") .enableHiveSupport() .getOrCreate(); spark.sparkContext().setLogLevel("DEBUG"); Dataset<Row> sqlDF = spark.read().table("company.emp_source"); sqlDF.write().mode(SaveMode.Overwrite).format("csv").saveAsTable("company.employee"); spark.close();
差异原因
Spark创建表的元数据存储逻辑
通过saveAsTable创建的表属于Spark管理的托管表(Managed Table),Spark会在集成的Hive Metastore中写入完整的CatalogTable元数据,包括表类型、存储提供者、创建者、生命周期等Spark专属元信息。当Spark读取这类表时,会直接从Catalog加载完整元数据,因此LogicalPlan中会明确引用CatalogTable对象。Hive原生表的Spark解析逻辑
Hive CLI创建的表属于Hive原生表,Spark在读取时,若遇到以下情况会退化为直接解析存储路径:- 表的存储格式或元数据配置包含Hive专属特性,Spark Catalog无法完全兼容解析;
- Spark的元数据转换配置(如
spark.sql.hive.convertMetastoreXXX系列参数)未开启,导致Spark优先读取底层存储路径而非加载Catalog元数据; - 表为Hive外部表时,Spark可能会优先识别存储路径,但元数据仍保存在Hive Metastore中。
判断第二种场景下的数据源是否为Hive表
可以通过以下三种方式验证:
方式1:执行Spark SQL查看扩展元数据
在Spark中执行DESCRIBE EXTENDED company.employee,查看输出内容:- 若包含
Database: company、Owner、Created By: Hive等字段,说明该表的元数据存在于Hive Metastore中,属于Hive表; - 若仅显示路径和字段信息,无Catalog相关元数据,才是纯路径数据源。
- 若包含
方式2:通过Spark Catalog API验证
在代码中调用Catalog接口获取表信息:try { CatalogTable table = spark.catalog().getTable("company.employee"); // 能获取到对象则说明是Hive表,可打印元数据确认 System.out.println(table.toString()); } catch (Exception e) { // 抛出异常则说明未在Catalog中注册,是纯路径数据源 }方式3:对比Hive元数据
在Hive CLI中执行DESCRIBE FORMATTED company.employee,将输出的元数据(如存储路径、表类型、创建时间)与Spark读取时的信息对比,若完全一致,说明该表是关联Hive元数据的Hive表。
内容的提问来源于stack exchange,提问作者Gurupraveen
相关产品推荐
相关产品推荐

