Hudi Schema Evolution 详解

2024-07-22 warehouse hudi

简介

Hudi 的 Schema 通过 AVRO 格式定义,常见的一些内置数据会在 hudi-common/src/main/avro 中定义,例如 HoodieMetadata.avsc 定义元数据。

BaseLog 的数据文件中都保存了写入数据时的相关表结构信息。

Spark

使用时不同的 Spark 版本启动参数略有区别,详细可以参考 Spark Quick Start 中的详细介绍,对于 Schema Evolution 来说,关键的是如下的配置。

spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog

修改表结构之后,会通过 deltacommitTimeline 信息中保存当前的表结构信息,在 inflight 中对应了 "operationType": "ALTER_SCHEMA",而在结束时包含了之前以及当前的 Schema 信息。

当配置了 hoodie.schema.on.read.enable=true 参数后,也就是开启 On Read 配置,会同时在 .hoodie/.schema 目录下保存对应的元数据。

源码解析

读取

TableSchemaResolver.getTableAvroSchema() 默认最新,可以指定 Instant 获取某个时间点
 |-HoodieTimeline.findInstantsBeforeOrEquals() 过滤某个之间点之前,如果传入的时间戳,否则直接调用如下函数
 |-TableSchemaResolver.getTableAvroSchemaInternal() 将 Instant 作为 Optional 参数传入
   |-TableSchemaResolver.getTableSchemaFromCommitMetadata() 根据 Instant 获取
   |-TableSchemaResolver.getTableSchemaFromLatestCommitMetadata() 获取最新
   |-HoodieTableConfig.getTableCreateSchema() 如果获取不到,则从 Properties 中获取
   |-TableSchemaResolver.getTableAvroSchemaFromDataFileInternal()
     |-TableSchemaResolver.getLatestCommitMetadataWithValidData()
     | |-HoodieActiveTimeline.getLatestCommitMetadataWithValidData()
     |   |-HoodieActiveTimeline.getCommitMetadataStream() 会读取 Timeline 中的内容,返回数据文件还存在的第一个 Instant 信息
     |-TableSchemaResolver.fetchSchemaFromFiles()
       |-TableSchemaResolver.readSchemaFromLogFile()
       |-TableSchemaResolver.readSchemaFromBaseFile()