SparkSQL执行Hudi表Upsert命令时遭遇数字格式异常问题
问题现象
在SparkSQL中对Hudi表执行Upsert命令时,抛出HoodieUpsertException,核心错误为java.lang.NumberFormatException: 输入字符串"7df51087"无法转换为数字,涉及的_hoodie_partition_path值为7df51087-9850-4060-b4c3-xxxxxx.parquet。
完整错误栈如下:
org.apache.hudi.exception.HoodieUpsertException: 提交时间20240214115154398的Upsert操作失败
at org.apache.hudi.table.action.commit.BaseWriteHelper.write(BaseWriteHelper.java:74)
at org.apache.hudi.table.action.commit.SparkUpsertCommitActionExecutor.execute(SparkUpsertCommitActionExecutor.java:44)
at org.apache.hudi.table.HoodieSparkCopyOnWriteTable.upsert(HoodieSparkCopyOnWriteTable.java:114)
at org.apache.hudi.table.HoodieSparkCopyOnWriteTable.upsert(HoodieSparkCopyOnWriteTable.java:103)
at org.apache.hudi.client.SparkRDDWriteClient.upsert(SparkRDDWriteClient.java:142)
at org.apache.hudi.DataSourceUtils.doWriteOperation(DataSourceUtils.java:224)
at org.apache.hudi.HoodieSparkSqlWriter$.writeInternal(HoodieSparkSqlWriter.scala:431)
at org.apache.hudi.HoodieSparkSqlWriter$.write(HoodieSparkSqlWriter.scala:132)
at org.apache.spark.sql.hudi.command.InsertIntoHoodieTableCommand$.run(InsertIntoHoodieTableCommand.scala:108)
at org.apache.spark.sql.hudi.command.InsertIntoHoodieTableCommand.run(InsertIntoHoodieTableCommand.scala:61)
at org.apache.spark.sql.execution.command.ExecutedCommandExec.sideEffectResult$lzycompute(commands.scala:75)
at org.apache.spark.sql.execution.command.ExecutedCommandExec.sideEffectResult(commands.scala:73)
根因错误栈:
java.lang.NumberFormatException: 输入字符串"7df51087"无法转换为数字
at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.base/java.lang.Integer.parseInt(Integer.java:652)
at java.base/java.lang.Integer.parseInt(Integer.java:770)
at org.apache.hudi.index.bucket.BucketIdentifier.bucketIdFromFileId(BucketIdentifier.java:79)
at org.apache.hudi.index.bucket.HoodieSimpleBucketIndex.getLocationMapper(HoodieSimpleBucketInd...
核心根因
Hudi的Simple Bucket Index在解析文件ID时,默认尝试将文件ID的前缀部分(此处为7df51087)按十进制整数解析,但该前缀是十六进制格式的字符串,无法直接转换为十进制整数,因此触发NumberFormatException。
解决方案
调整Bucket Index的文件ID解析逻辑
若使用自定义Bucket Index实现,需修改BucketIdentifier.bucketIdFromFileId方法,指定按十六进制解析字符串:// 替换原Integer.parseInt(fileIdPrefix)调用 int bucketId = Integer.parseInt(fileIdPrefix, 16);若使用Hudi官方版本,建议升级到已修复该问题的版本(如Hudi 0.14.x及后续版本,需验证对应版本的解析逻辑)。
切换索引类型
若暂时无法修改或升级Hudi版本,可将表的索引类型从SIMPLE_BUCKET替换为其他兼容类型,例如:- BLOOM:基于布隆过滤器的索引,适配多数业务场景
- GLOBAL_BLOOM:全局布隆索引
- INMEMORY:内存索引(适合小数据量表)
修改表属性的示例SQL:
ALTER TABLE your_hudi_table SET TBLPROPERTIES ( 'hoodie.index.type' = 'BLOOM' );自定义文件ID生成策略
若必须使用Simple Bucket Index,可通过配置Hudi参数自定义文件ID生成逻辑,确保文件ID前缀为十进制数字。该方式复杂度较高,仅作为备选方案。
内容的提问来源于stack exchange,提问作者SAUMYA

