COW(Copy-on-Write)
COW(Copy-on-Write)更新流程如下
-
首先,对要更新的数据进行去重,确保每个记录只有一个条目。这是为了避免多个记录更新同一个键,导致数据不一致。
-
对这批数据创建索引,将HoodieKey(包含键和分区信息)映射到HoodieRecordLocation(包含文件ID和记录偏移量)。创建索引 (HoodieKey => HoodieRecordLocation);通过索引区分哪些 records 是 update,哪些 records 是 insert(key 第一次写入)。这个索引可以帮助我们快速查找要更新的记录所在的文件和位置。
-
对于 update 消息,会直接找到对应 key 所在的最新 FileSlice 的 base 文件,并做 merge 后写新的 base file (新的 FileSlice)
-
对于 insert 消息,会扫描当前 partition 的所有 SmallFile(小于一定大小的 base file),然后 merge 写新的 FileSlice;如果没有 SmallFile,直接写新的 FileGroup + FileSlice
这个流程可以保证数据的一致性和可靠性,因为它使用了Copy-on-Write的策略,即每次更新都会生成一个新的数据文件,而不是直接在原始文件上进行修改。这样可以避免原始文件被损坏,同时也可以保留所有历史版本的数据。
MOR(Merge-on-Read)
MOR(Merge-on-Read)更新流程如下:
-
首先,对要更新的数据进行去重,对 records 按照 record key 去重(可选),确保每个记录只有一个条目。这是为了避免多个记录更新同一个键,导致数据不一致。
-
对这批数据创建索引,将HoodieKey(包含键和分区信息)映射到HoodieRecordLocation(包含文件ID和记录偏移量)。创建索引 (HoodieKey => HoodieRecordLocation);通过索引区分哪些 records 是 update,哪些 records 是 insert(key 第一次写入).这个索引可以帮助我们快速查找要更新的记录所在的文件和位置。
- 2.1如果是 insert 消息,如果 log file 不可建索引(默认),会尝试 merge 分区内最小的 base file (不包含 log file 的 FileSlice),生成新的 FileSlice;如果没有 base file 就新写一个 FileGroup + FileSlice + base file;如果 log file 可建索引,尝试 append 小的 log file,如果没有就新写一个 FileGroup + FileSlice + base file
- 2.2 如果是 update 消息,写对应的 file group + file slice,直接 append 最新的 log file(如果碰巧是当前最小的小文件,会 merge base file,生成新的 file slice)
-
对于要更新的记录,通过索引找到它们所在的文件和位置。然后,将它们写入到一个新的日志文件中。如果日志文件大小达到阈值,就会创建一个新的日志文件。
-
对于要插入的记录,如果日志文件大小不超过阈值,就将它们写入到当前日志文件中。否则,如果当前没有已经建立索引的基础文件,就创建一个新的文件组和文件切片,并将记录写入到一个新的基础文件中。如果当前有已经建立索引的基础文件,则在最小的基础文件上进行合并,生成新的文件切片和基础文件。
-
对于要更新的记录,将它们写入到对应的文件组和文件切片中。如果当前的文件切片大小不超过阈值,就将记录追加到当前文件切片中。否则,如果当前文件切片没有基础文件,就创建一个新的基础文件,并将记录写入到其中。如果当前文件切片有基础文件,则在最小的基础文件上进行合并,生成新的文件切片和基础文件。
-
对于要删除的记录,将它们标记为已删除,并写入到对应的文件组和文件切片中。
-
对于每个文件切片,创建索引,以加速查询和更新操作。
MOR的优点是它的存储开销较小,因为它只需要一个视图文件。它还可以快速地查询和删除数据,因为所有的数据都在一个文件中。但是,缺点是它的更新速度较慢,因为它需要将原始数据文件和更新数据文件合并成一个视图文件。
总的来说,COW适用于更新数据量较小的情况,而MOR适用于更新数据量较大的情况。
标签:文件,Hudi,FileSlice,记录,流程,更新,索引,file,UPSERT From: https://blog.51cto.com/hiszm/6221941