)
数据湖湖仓一体大数据数据存储【免费下载链接】hudiUpserts, Deletes And Incremental Processing on Big Data.项目地址https://gitcode.com/gh_mirrors/hud/hudi点击查看免费下载Hudi 的CustomKeyGenerator允许在一张表上按字段粒度混用不同的分区键生成策略既可以用字段原值直接作为分区SIMPLE也可以把时间戳字段格式化为yyyy-MM-dd之类的日期目录TIMESTAMP从而满足国家 日期这类复合分区场景。本文以仓库中hudi-trino连接器的测试数据集hudi_custom_keygen_pt_v8_mor为骨架完整还原其建表脚本与配置并结合CustomKeyGenerator源码和 Trino 测试初始化器讲解如何创建、写入并验证一张带自定义键生成器的 MOR 表。一、这张测试表要解决什么问题在 hudi-trino/src/test/resources/hudi-testing-data/hudi_custom_keygen_pt_v8_mor.md 中该测试数据的创建脚本说明了表的形态表类型MOR读时合并表使用CustomKeyGenerator生成记录键与分区路径数据版本Hudi Table Revisionf7157954a9819137446d8e3a1d331d003f069414仓库里同时存在对应的 hudi_custom_keygen_pt_v8_mor.zip 归档供 Trino 集成测试直接解压使用文件形态无 log 文件未触发增量日志写入/compaction测试时通过关闭 inline compaction 保证表保持纯 base file 状态。它属于 hudi-trino/src/test/resources/hudi-testing-data 目录下带分区路径的 MOR 表系列测试数据之一同系列还包括hudi_timestamp_keygen_pt_epoch_to_yyyy_mm_dd_hh_v8_mor、hudi_multi_pt_v8_mor等专门用于验证 Trino Hudi 连接器对各类 keygen/分区形态的读取兼容性。二、建表脚本混合 SIMPLE 与 TIMESTAMP 分区类型以下是该文档提供的完整建表脚本保留原始注释它将两个分区字段分别声明为不同分区键类型test(Create MOR table with custom keygen partition field) { withTempDir { tmp val tableName hudi_custom_keygen_pt_v8_mor spark.sql( s |CREATE TABLE $tableName ( | id INT, | name STRING, | price DOUBLE, | ts LONG, | -- Partition Source Fields -- | partition_field_country STRING, | partition_field_date BIGINT |) USING hudi | LOCATION ${tmp.getCanonicalPath} | TBLPROPERTIES ( | primaryKey id, | type mor, | preCombineField ts, | -- Timestamp Keygen and Partition Configs -- | hoodie.table.keygenerator.class org.apache.hudi.keygen.CustomKeyGenerator, | hoodie.datasource.write.partitionpath.field partition_field_country:SIMPLE,partition_field_date:TIMESTAMP, | hoodie.keygen.timebased.timestamp.type EPOCHMILLISECONDS, | hoodie.keygen.timebased.output.dateformat yyyy-MM-dd, | hoodie.keygen.timebased.timezone UTC | ) PARTITIONED BY (partition_field_country, partition_field_date) .stripMargin) // To not trigger compaction scheduling, and compaction spark.sql(sset hoodie.compact.inline.max.delta.commits9999) spark.sql(sset hoodie.compact.inlinefalse) // Configure Hudi properties spark.sql(sSET hoodie.metadata.enabletrue) spark.sql(sSET hoodie.metadata.index.column.stats.enabletrue) // Insert data with new partition values spark.sql(sINSERT INTO $tableName VALUES(1, a1, 100.0, 1000, SG, 1749284360000)) spark.sql(sINSERT INTO $tableName VALUES(2, a2, 200.0, 1000, SG, 1749204000000)) spark.sql(sINSERT INTO $tableName VALUES(3, a3, 101.0, 1001, US, 1749202000000)) spark.sql(sINSERT INTO $tableName VALUES(4, a4, 201.0, 1001, CN, 1749102000000)) spark.sql(sINSERT INTO $tableName VALUES(5, a5, 300.0, 1002, MY, 1747102000000)) spark.sql(sINSERT INTO $tableName VALUES(6, a6, 301.0, 1000, SG, 1749284360000)) spark.sql(sINSERT INTO $tableName VALUES(7, a7, 401.0, 1000, SG, 1749204000000)) // Generate logs through updates // NOTE: The query below will throw an error // spark.sql(sUPDATE $tableName SET price ROUND(price * 1.02, 2)) // NOTE: The query below will throw an error // spark.sql(sSELECT * FROM $tableName).show(false) } }脚本同时给出了三条关键运行期配置配置项值作用hoodie.compact.inline.max.delta.commits9999抬高触发 inline compaction 的 delta commit 阈值防止测试过程中自动触发合并保持无 log 文件的期望形态hoodie.compact.inlinefalsefalse显式关闭 inline compactionhoodie.metadata.enabletrue开启 Hudi 元数据表hoodie.metadata.index.column.stats.enabletrue在元数据表中构建列统计索引供查询裁剪column stats index使用关于末尾两行注释需要说明UPDATE与SELECT *在脚本中被注释并标注会抛错这是测试数据生成脚本在特定 Spark 会话/环境下的行为约束读者在自己的环境里复现时不一定复现同样的错误但生成数据文件本身并不依赖这两条语句。三、CustomKeyGenerator 的分区键解析原理hoodie.table.keygenerator.class org.apache.hudi.keygen.CustomKeyGenerator指向 hudi-client/hudi-spark-client/src/main/java/org/apache/hudi/keygen/CustomKeyGenerator.java。该类是一个通用键生成器核心设计是分区字段配置格式hoodie.datasource.write.partitionpath.field按字段名:分区键类型,字段名:分区键类型的逗号分隔格式声明每个字段可以挂不同的类型逐字段分配生成器构造时对每个分区字段调用getPartitionKeyGenerators解析出PartitionKeyType后分发到对应的内置生成器——SIMPLE类型交给SimpleKeyGeneratorTIMESTAMP类型交给TimestampBasedKeyGenerator见 CustomKeyGenerator.java记录键record key根据primaryKey字段个数决定——单字段用SimpleKeyGenerator多字段组合用ComplexKeyGenerator分区路径拼接多个分区字段生成的值按顺序用分隔符/拼接成完整分区路径。在 Avro 数据写入路径上有对应的 hudi-client/hudi-client-common/src/main/java/org/apache/hudi/keygen/CustomAvroKeyGenerator.java 实现同样的逻辑其PartitionKeyType枚举仅支持SIMPLE与TIMESTAMP两种见 CustomAvroKeyGenerator.java并提供getPartitionFieldAndKeyType做field:Type的解析与合法性校验。所以本表中partition_field_country:SIMPLE,partition_field_date:TIMESTAMP的含义是partition_field_country按SIMPLE处理分区目录直接用字段原值如SG、US、CN、MYpartition_field_date按TIMESTAMP处理把 BIGINT 类型的时间戳毫秒按配置格式化为日期字符串如2025-06-06作为分区目录。两个字段组合后产生的分区路径形如SG/2025-06-06、US/2025-06-06。四、TIMESTAMP 类型分区的三项关键配置时间戳分区行为由hoodie.keygen.timebased.*系列配置控制本例中的三项配置直接决定了分区目录长什么样配置项本例值说明hoodie.keygen.timebased.timestamp.typeEPOCHMILLISECONDS输入时间戳的格式类型。EPOCHMILLISECONDS表示输入值为 Unix 毫秒时间戳另支持EPOCHSECONDS、SCALAR以及TIMESTAMP_MILLIS/TIMESTAMP_MICROS等类型hoodie.keygen.timebased.output.dateformatyyyy-MM-dd输出分区目录的日期格式。本例输出到天粒度若要细分到小时可写成yyyy-MM-dd HH同目录下的hudi_timestamp_keygen_pt_epoch_to_yyyy_mm_dd_hh_v8_mor即采用小时粒度hoodie.keygen.timebased.timezoneUTC时间戳换算时使用的时区。时区不同会导致同一毫秒值落在不同日历日期生产环境务必与业务语义对齐这些配置在KeyGeneratorOptions中均有对应的配置键定义例如hoodie.datasource.write.recordkey.field、hoodie.datasource.write.partitionpath.field定义在 hudi-common/src/main/java/org/apache/hudi/keygen/constant/KeyGeneratorOptions.java其中PARTITIONPATH_FIELD_NAME明确指出实际取值通过对字段值调用 toString() 获得。时区换算验证7 条数据如何落成 5 个分区脚本中 7 条 INSERT 的毫秒时间戳在UTC、yyyy-MM-dd格式下换算结果如下记录国家字段毫秒时间戳换算出的日期分区最终分区路径id1SG17492843600002025-06-07SG/2025-06-07id2SG17492040000002025-06-06SG/2025-06-06id3US17492020000002025-06-06US/2025-06-06id4CN17491020000002025-06-05CN/2025-06-05id5MY17471020000002025-05-13MY/2025-05-13id6SG17492843600002025-06-07SG/2025-06-07id7SG17492040000002025-06-06SG/2025-06-067 条记录最终收敛为 5 个唯一分区US/2025-06-06、CN/2025-06-05、MY/2025-05-13、SG/2025-06-06、SG/2025-06-07。这与 Trino 测试初始化器中注册的分区集合完全一致见下文第五节可据此验证建表配置的正确性。五、测试数据在 Trino 连接器中的注册与使用该 zip 归档在 Trino 集成测试中由 hudi-trino/src/test/java/io/trino/plugin/hudi/testing/ResourceHudiTablesInitializer.java 消费。其工作流程为initializeTables把hudi-testing-data资源目录下所有 zip 解压到临时目录再通过copyDir拷贝到测试文件系统并对每个文件做 SHA-256 校验拷贝后重读比对哈希防止损坏TestingTable枚举中的HUDI_CUSTOM_KEYGEN_PT_V8_MOR条目注册了该表的数据列、分区列与分区路径见 ResourceHudiTablesInitializer.java数据列id INT、name STRING、price DOUBLE、ts LONG与建表脚本一致另叠加_hoodie_*元数据列分区列partition_field_country STRING、partition_field_date STRING——注意存储为 Hive 分区值时日期已被格式化为字符串即 keygen 的输出值同步进了 metastore分区映射partition_field_countryUS/partition_field_date2025-06-06等 5 个分区恰好对应建表脚本插入数据后生成的 5 个分区路径该条目isCreateRtTablefalse即只为这张 MOR 表创建默认的 roRead Optimized外部表不额外创建_rt实时表。另外注意copyDir中有一条值得留意的过滤逻辑跳过所有.crc文件注释明确说明Hudi 遇到 crc 文件会出问题这也是在本地/云存储上部署 Hudi 表时容易踩的坑之一。六、复现与验证要点总结要把这张表从文档脚本复现成可查询的表建议按以下顺序操作建表在 Spark 3.x Hudi 写端环境中按上文CREATE TABLE脚本执行LOCATION指向你的存储路径primaryKey、preCombineField、type是必填的 Spark SQL Hudi 表属性关闭 inline compactionhoodie.compact.inlinefalsehoodie.compact.inline.max.delta.commits9999保证测试期间不产生 log 文件合并维持MOR 但无 log的状态便于后续以纯 base file 形态验证查询写入执行 7 条INSERT INTO ... VALUES(...)字段顺序为(id, name, price, ts, partition_field_country, partition_field_date)验证分区到表路径下检查目录结构应出现partition_field_countrySG/partition_field_date2025-06-06之类的 5 个分区若开启 hive_style_partitioning 则为keyvalue形式否则为裸值路径对照第五节的分区映射确认 keygen 行为接入 Trino将该表目录作为外部表挂载后用 ResourceHudiTablesInitializer.java 同款方式解压 zip → 建外部表 → 注册分区即可让 Trino 通过 Hudi 连接器读取。七、结语hudi_custom_keygen_pt_v8_mor测试数据是理解 HudiCustomKeyGenerator的一手教材它同时演示了 SIMPLE 与 TIMESTAMP 两种分区键类型如何在同一条hoodie.datasource.write.partitionpath.field中混用、时间戳分区配置如何影响目录粒度、以及这种表形态在 Trino 连接器中如何被注册和校验。结合 CustomKeyGenerator.java 与 CustomAvroKeyGenerator.java 的源码可以完整串联建表配置 → keygen 解析 → 分区目录生成 → 查询端读取的全链路。如果你的业务同样需要按国家分区 按天分区的复合布局直接复用本文的配置组合即可快速落地。赞分享数据湖湖仓一体大数据数据存储【免费下载链接】hudiUpserts, Deletes And Incremental Processing on Big Data.项目地址https://gitcode.com/gh_mirrors/hud/hudi点击查看免费下载相关推荐Hudi 多分区字段 MOR 表的 Spark SQL 建表与 Trino 分区裁剪实战基于 hudi-trino 测试数据集Hudi 多分区字段 MOR 表的 Spark SQL 建表与 Trino 分区裁剪实战基于 hudi trino 测试数据集 导读 本文以 Apache数据湖湖仓一体大数据数据存储构建多文件组分区 MOR 测试数据集Apache Hudi Trino 连接器索引跳过与分区剪枝验证实战构建多文件组分区 MOR 测试数据集Apache Hudi Trino 连接器索引跳过与分区剪枝验证实战 这篇技术指南围绕 Apache Hudi 仓库中面向数据湖湖仓一体大数据数据存储Apache Hudi 非分区 MOR 测试表生成指南基于 hudi_non_part_mor 的 Trino 连接器测试实践Apache Hudi 非分区 MOR 测试表生成指南基于 hudi_non_part_mor 的 Trino 连接器测试实践 本文以 Hudi 仓库中 hu数据湖湖仓一体大数据数据存储上一篇如何在ARM设备上高效运行x86_64程序Box64终极兼容方案实战指南下一篇SeetaFace6完整指南9大功能构建专业人脸识别系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考