Hudi中数据重复

针对Hudi MergeOnRead表在增量写入时出现的跨分区重复数据问题,解决方案是启用全局(布隆)索引,并设置HoodieIndexConfig.BLOOM_INDEX_UPDATE_PARTITION为true,以实现全局数据去重。默认情况下,Hudi仅处理同分区内的数据去重,开启全局索引可以确保全表范围内的唯一性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

问题描述:

往Hudi MOR(Merge On Read)表增量写数据,发现数据并没有按主键合并,存在重复数据.

主键...分区
1...P_1
2...P_1
1...P_2
3...P_2
4...P_2

解决方法:

          经分析重复数据只存在于不同分区内,如主键为1的数据,同分区内不存在重复数据。基于此可以使用全局(布隆)索引并设置HoodieIndexConfig.BLOOM_INDEX_UPDATE_PARTITION为true.

出于性能考虑,Hudi默认只对同分区内的数据去重,需要全局去重需要开启全局索引

### 使用 Apache Hudi 创建表并插入数据 #### 表格创建与数据插入概述 Apache Hudi 提供了一种高效的方式来管理和操作大数据集。Hudi 支持两种主要的表类型:Copy On Write (COW) 和 Merge On Read (MOR)[^4]。每种类型的表都具有不同的性能特点和适用场景。 以下是基于 Scala 编程语言的一个简单示例,展示如何在 Copy On Write (COW) 模式下创建 Hudi 表并将数据插入其中[^5]。 --- #### 示例代码:创建 COW 表并插入数据 ```scala import org.apache.hudi.DataSourceWriteOptions._ import org.apache.hudi.config.HoodieWriteConfig._ import org.apache.spark.sql.SaveMode import org.apache.spark.sql.functions._ // 初始化 SparkSession val spark = org.apache.spark.sql.SparkSession.builder() .appName("Hudi Insert Example") .getOrCreate() // 设置 Hudi 配置参数 val hudiOptions = Map( "hoodie.datasource.write.recordkey.field" -> "id", // 定义主键字段 "hoodie.datasource.write.partitionpath.field" -> "partition_field", // 分区字段 "hoodie.datasource.write.precombine.field" -> "ts", // 时间戳字段 "hoodie.insert.shuffle.parallelism" -> "2", "hoodie.upsert.shuffle.parallelism" -> "2" ) // 构建要写入的数据框 val data = Seq( (1, "Alice", "2023-09-01T10:00:00Z"), (2, "Bob", "2023-09-01T10:05:00Z"), (3, "Charlie", "2023-09-01T10:10:00Z") ).toDF("id", "name", "ts") data.withColumn("partition_field", lit("part_0")) // 添加分区列 // 将数据保存到 Hudi 表中 val basePath = "s3://your-bucket/path/to/hudi-table" // 替换为目标路径 data.write.format("hudi") .options(hudiOptions) .option(PRECOMBINE_FIELD.key(), "ts") // 设置时间戳字段 .option(RECORDKEY_FIELD.key(), "id") // 设置主键字段 .option(PARTITIONPATH_FIELD.key(), "partition_field") // 设置分区字段 .mode(SaveMode.Append) .save(basePath) spark.stop() ``` --- #### 关键配置说明 1. **`hoodie.datasource.write.recordkey.field`**: 定义唯一标识每一行记录的字段名称。 2. **`hoodie.datasource.write.partitionpath.field`**: 指定用于分片存储的字段名。 3. **`hoodie.datasource.write.precombine.field`**: 当存在重复记录时,指定哪个字段作为优先级依据(通常为时间戳字段)。 4. **`basePath`**: 存储 Hudi 表的实际位置,可以是本地文件系统或 Amazon S3 路径[^2]。 --- #### 数据读取方式 对于刚刚创建的 COW 表,可以通过以下方法读取其内容: ```scala val readData = spark.read.format("hudi").load(basePath) readData.show() ``` 如果涉及增量数据,则需额外引入 `MergeOnRead` 方式的逻辑处理[^3]。 --- #### 注意事项 - 在实际生产环境中,建议优化 shuffle 并发度以及调整其他高级选项以提升性能。 - 如果使用的是 MOR 表型,则需要进一步定义 DeltaLog 的管理策略。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CoderFusionZhu

不要打赏太多哦!我喝速溶就行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值