Spark读取hive表元数据异常

目录

业务背景

涉及过程

操作步骤:

尝试MSCK REPAIR TABLE

尝试REFRESH TABLE

REFRESH TABLE和MSCK REPAIR TABLE区别

验证

报错日志

结论与建议

建议


业务背景

在 ETL 过程中,向表中新增字段时,由于表的特殊性质,存在实时接入和更新三个月历史数据的情况,导致小文件过多。使用 Hive 增加字段时,Spark 的 schema 没有立即生效,这会造成 Hive 表的元数据与 Spark SQL 的 schema 不一致。需要通过 REFRESH TABLE 命令刷新表,同时要求没有其他任务同时操作该表(包括插入和读取),以确保数据一致性。

当使用 Spark Streaming 更新 Hive 表时,可能会出现以下问题:

  • 警告信息:WARN HiveExternalCatalog:The table schema given by Hive metastore...,表明 Spark 无法使用 Hive 存储的元数据,需要从所有分区表中读取元数据信息。
  • Spark 任务卡在 Listing leaf files 阶段,尽管只对部分分区进行了更新,但 Listing 过程却扫描了所有分区(如 500 个分区)。

涉及过程

操作步骤

  • 修改 MySQL 配置:在 ETL 字段中进行更改,同时通过 Hive 命令增加字段。
alter table table  add columns (***) cascade;
  • 执行刷新操作:使用 Spark Shell 执行 REFRESH TABLE 命令,相比直接使用 Spark SQL,Spark Shell 执行速度更快。示例命令:
--history |grep spark-shell24
​
spark-shell24  --conf spark.dynamicAllocation.maxExecutors=100 --conf spark.dynamicAllocation.minExecutors=10 --executor-memory 25g --executor-cores 5 --conf spark.sql.shuffle.partitions=2000 --driver-memory 16g --queue root.yarn_etl.etl  --conf spark.driver.maxResultSize=5g
​
spark.sql("REFRESH TABLE   table")

尝试MSCK REPAIR TABLE

尝试使用MSCK REPAIR TABLE修复表,执行成功,同时对结果未有影响

尝试REFRESH TABLE

尝试其他命令

  • MSCK REPAIR TABLE:修复表结构,无明显效果。
  • 手动修改 Hive 元数据:考虑修改 Hive 元数据中的 Spark schema 缓存属性,但因风险较大,未进行操作。
  • 生成新表:如果无法解决,考虑生成新表并同步历史数据,但会影响后续的 ETL 任务。

其语法如下:

:Set Table Properties:添加或修改TBLPROPERTIES
ALTER TABLE table identifier SET TBLPROPERTIES(key1=val1,key2 =val2,...)
--Unset Table Properties:删除TBLPROPERTIES
ALTER TABLE table identifier UNSET TBLPROPERTIES [ IF EXISTS ]( key1, key2, ...

REFRESH TABLEMSCK REPAIR TABLE区别

在Spark中,REFRESH TABLEMSCK REPAIR TABLE都与元数据管理和表分区有关,但它们有不同的作用和用法。

  1. REFRESH TABLE

    • REFRESH TABLE命令用于刷新表的元数据。当表的元数据发生变化(比如添加、删除、修改分区),但这些变化没有被及时反映到Spark的元数据缓存中时,你可以使用REFRESH TABLE命令来强制Spark重新加载这些元数据,以确保Spark中的元数据与数据存储中的实际情况保持一致。

    • 这个命令通常用于当你手动添加或删除了表的分区时,为了让Spark能够识别到这些变化,你需要执行REFRESH TABLE

  2. MSCK REPAIR TABLE

    • MSCK REPAIR TABLE命令用于修复表的分区,特别是针对外部表(external tables)。

    • 当你有一个外部表,数据被添加到了表的分区目录中,但是表的元数据没有被相应地更新,这时你可以运行MSCK REPAIR TABLE命令来检测分区目录中的数据,并更新表的元数据,以便Spark能够识别到这些分区。

    • 这个命令通常用于处理外部表的分区,因为外部表的分区通常不是由Spark管理的,而是由外部数据源(如Hive、HDFS)管理的。因此,使用MSCK REPAIR TABLE可以确保Spark中的元数据与外部数据源中的实际情况保持一致。

总的来说,REFRESH TABLE用于刷新表的元数据,而MSCK REPAIR TABLE用于修复外部表的分区。在使用时需要根据具体的情况选择合适的命令。

验证

--查询desc formatted 表名 partition(day=20240301);看要加的字段加上去没有
desc formatted sdk_public.mobpush_event_detail  partition(day=20240301);
--查询表字段
desc 表名 

问题点:通过上面的命令不管是表还是分区,字段都是加上的,同时后面执行还是会走的Listing leaf files这一步

报错日志

24/03/05 20:20:33 WARN org.apache.spark.internal.Logging: The table schema given by Hive metastore(struct<workid:string,rid:string,duid:string,sdkver:string,appkey:string,push_channel:string,plat:int,time:bigint,type:int,sub_type:int,factorycode:string,factorydesc:string,create_time:bigint,serdatetime:bigint,rdid:string,oiid:string,pkg:string,repeat:boolean,category:string,day:string>) is different from the schema when this table was created by Spark SQL(struct<workid:string,rid:string,duid:string,sdkver:string,appkey:string,push_channel:string,plat:int,time:bigint,type:int,sub_type:int,factorycode:string,factorydesc:string,create_time:bigint,serdatetime:bigint,rdid:string,oiid:string,pkg:string,repeat:boolean,day:string>). We have to fall back to the table schema from Hive metastore which is not case preserving.
如果在执行 REFRESH 命令的同时有其他进程正在写入文件,那么 REFRESH 命令的行为可能会受到这些写入操作的影响。具体行为取决于多个因素,包括你使用的具体系统、 REFRESH 命令的实现细节以及写入操作的性质。
1.Hive的 REFRESH 命令:
在Hive中, REFRESH 命令用于使Hive元数据与HDFS或其他存储系统同步。如果REFRESH 命令执行时,有新的文件被添加到HDFS中,那么这些新文件可能不会立即出现在Hive的元数据中,除非 REFRESH 命令能够检测到这些更改。然而,如果文件在 REFRESH 命令执行过程中被修改或删除那么这些更改可能会影响 REFRESH 命令的结果。
2.并发写入:
并发写入可能会影响 REFRESH 命令的行为。如果写入操作是在Hive表的数据目录中进行的,并且这些更改在 REFRESH 命令执行时还没有完成,那么这些更改可能不会立即反映在Hive的元数据中。
3.事务性:
如果你的系统支持事务性操作,那么 REFRESH 命令可能会等待所有并发写入操作完成后再进行元数据更新,以确保数据的一致性。
4.文件系统的特性:
底层文件系统的特性也会影响 REFRESH 命令的行为。例如,某些文件系统可能支持即时检测到新添加的文件,而其他文件系统可能需要一段时间才能检测到这些更改。
总之,如果在执行 REFRESH 命令的同时有其他进程正在写入文件,那么 REFRESH 命令的行为可能会受到影响。为了确保数据的一致性,最好在执行 REFRESH 命令之前暂停写入操作,或者在 REFRESH 命令执行后验证数据的完整性。此外,根据你所使用的系统和框架,查阅相关文档以了解 REFRESH 命令的具体行为和限制也是一个好主唐

结论与建议

结论:

  1. 元数据不一致问题:在你的ETL过程中,由于Spark和Hive的元数据未能同步,导致了表的元数据信息和schema不一致的问题。这可能是由于Hive在添加字段后,Spark没有立即刷新其缓存的元数据所致。

  2. Spark Streaming与Hive集成问题:在使用Spark Streaming更新Hive表时,由于Spark无法使用Hive存储的元数据,导致了任务失败。这可能是因为Spark Streaming在处理Hive表时,没有正确地获取到最新的元数据。

建议

  1. 暂停写入操作:在执行 REFRESH TABLE 前,暂停对表的写入操作,确保数据的一致性。
  2. 验证刷新效果:在执行 REFRESH TABLE 后,验证表结构和字段是否正确更新。
  3. 小文件合并:定期进行小文件合并,减少小文件的数量,以提高操作效率。
  4. 监控并发写入:避免在进行元数据刷新时有其他进程同时操作该表,特别是大规模数据处理任务。
  5. 考虑表结构优化:如果频繁遇到此类问题,考虑优化表的结构和分区策略,减少对元数据的频繁更新。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值