Hudi表数据重复原因

测试中,发现虽然显示设置为 upsert,且也按规范设置了 primaryKey、preCombineField,type 等,但查出的结果仍然存在重复。反复测试,重复的数据稳定为 2,且同一数据的一笔提交时间也保持不变。结果显示同一数据分区相同,但来自不同的 HDFS 文件。

相关Issue

这个问题的原因是 drop 掉一张 hudi 表时,对应的表文件没有被删除,导致以同样路径再次创建后,select 仍然能查出来,这时显示重复的原因。但反复 create 和 drop,总是只有两个文件,并没有增加新的。

Flink SQL> CREATE TABLE `default_catalog`.`default_database`.`t06` (
>   `ds` BIGINT,
>   `ut` VARCHAR(2147483647),
>   `pk` BIGINT NOT NULL,
>   `f0` BIGINT,
>   `f1` BIGINT,
>   `f2` BIGINT,
>   `f3` BIGINT,
>   CONSTRAINT `PK_3610` PRIMARY KEY (`pk`) NOT ENFORCED
> ) PARTITIONED BY (`ds`)
> WITH (
>   'connector' = 'hudi',
>   'index.type' = 'BUCKET',
>   'payload.class' = 'org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload',
>   'hoodie.compaction.payload.class' = 'org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload',
>   'hoodie.datasource.write.payload.class' = 'org.apache.hudi.common.model.OverwriteNonDefaultsWithLatestAvroPayload',
>   'path' = 'hdfs:///user/root/hudi/t06',
>   'connector' = 'hudi',
>   'precombine.field' = 'ut',
>   'table.type' = 'MERGE_ON_READ',
>   'write.operation' = 'upsert',
>   'hoodie.bucket.index.num.buckets' = '2'
> )
> ;
[INFO] Execute statement succeed.

Flink SQL> insert into t06 (ds,ut,pk,f0) select 20230101 ds,CAST(current_timestamp AS STRING) ut,1001 pk,1 f0;
[INFO] Submitting SQL update stat
### 如何在 Spark 中创建 Hudi 要在 Spark 中创建 Hudi ,可以通过以下方式实现。以下是具体的操作方法以及需要注意的关键点: #### 1. 配置环境 为了支持 Hudi 的功能,在启动 `spark-shell` 或者提交 Spark 应用程序之前,需要加载必要的依赖项并设置相应的配置参数。 ```bash ./bin/spark-shell \ --master local[*] \ --conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer' \ --conf 'spark.sql.extensions=org.apache.spark.sql.hudi.HoodieSparkSessionExtension' \ --conf 'spark.sql.catalog.spark_catalog=org.apache.spark.sql.hudi.catalog.HoodieCatalog' ``` 如果使用的是 YARN 模式,则可以调整 `--master` 参数为 `yarn`[^2]。 #### 2. 创建 Hudi Hudi 支持多种存储模式(COPY_ON_WRITE 和 MERGE_ON_READ),下面分别介绍如何基于这两种模式创建。 ##### (a) COPY_ON_WRITE 模式的建语句 以下是一个典型的 DDL 建语句,用于定义一个 COW 类型的 Hudi : ```sql CREATE TABLE hudi_cow_table ( id BIGINT, name STRING, price DOUBLE, ts TIMESTAMP, dt STRING ) USING hudi OPTIONS ( type='cow', primaryKey='id', preCombineField='ts' ) PARTITIONED BY (dt); ``` 此语句中的关键选项解释如下: - `type='cow'`: 定义该采用 Copy-On-Write 存储模型。 - `primaryKey='id'`: 设置主键字段,用于唯一标识每条记录。 - `preCombineField='ts'`: 当存在重复数据时,指定哪个时间戳字段作为最新的依据。 - `PARTITIONED BY (dt)`: 将数据按日期分区存储,便于查询优化[^1]。 ##### (b) MERGE_ON_READ 模式的建语句 MERGE_ON_READ 是另一种常见的存储模式,适用于频繁更新和增量处理场景。其建语法类似于 COW,只需更改类型即可: ```sql CREATE TABLE hudi_mor_table ( id BIGINT, name STRING, price DOUBLE, ts TIMESTAMP, dt STRING ) USING hudi OPTIONS ( type='mor', -- 使用 Merge-on-Read 模式 primaryKey='id', preCombineField='ts' ) PARTITIONED BY (dt); ``` 同样地,也可以通过编程接口动态构建 Schema 并写入数据Hudi 中。例如: ```scala import org.apache.spark.sql.SaveMode val df = spark.read.format("csv").option("header", "true").load("/path/to/data.csv") df.write.format("hudi"). options(Map( "hoodie.datasource.write.table.type" -> "COPY_ON_WRITE", "hoodie.datasource.write.precombine.field" -> "ts", "hoodie.datasource.write.recordkey.field" -> "id", "hoodie.datasource.write.partitionpath.field" -> "dt" )). mode(SaveMode.Append).save("/path/to/hudi/table") ``` 这段代码展示了如何利用 DataFrame API 向已存在的 Hudi 追加新数据[^3]。 #### 3. 解决常见问题 当尝试创建 Hudi 遇到异常时,可能是因为缺少某些 JAR 文件或未正确注册扩展类。此时可以根据错误提示定位原因,并采取相应措施解决。比如缺失 `HoodieParquetRealtimeInputFormat` 类的情况,需确认是否已经将 `hudi-hadoop-mr-bundle-x.y.z.jar` 添加到了 Hive Metastore 所使用的库路径下[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值