文章目录
- Copy On Write
- Merge On Read
- COW 与 MOR 的对比
- 查询类型(Query Types)
- Snapshot Queries
- Incremental Queries
- Read Optimized Queries
- 不同表支持的查询类型
Copy On Write
在 COW 表中,只有数据文件/基本文件(.parquet),没有增量日志文件(.log.*)。对每一个新批次写入都将创建相应数据文件的新版本(新的 FileSlice),新版本文件包括旧版本文件的记录以及来自传入批次的记录(全量最新)。
由于在写入期间进行合并,COW 会产生一些写入延迟。但是 COW 的优势在于它的简单性,不需要其他表服务(如压缩),也相对容易调试。
Merge On Read
MOR 表中,包含列存的基本文件(.parquet)和行存的增量日志文件(基于行的 avro 格式,.log.*)。
顾名思义,MOR 表的合并成本在读取端。因此在写入期间我们不会合并或创建较新的数据文件版本。标记/索引完成后,对于具有要更新记录的现有数据文件,Hudi 创建增量日志文件并适当命名它们,以便它们都属于一个文件组。
读取端将实时合并基本文件及其各自的增量日志文件。每次的读取延迟都比较高(因为查询时进行合并),所以 Hudi 使用压缩机制来将数据文件和日志文件合并在一起并创建更新版本的数据文件。
用户可以选择内联或异步模式运行压缩。Hudi 也提供了不同的压缩策略供用户选择,最常用的一种是基于提交的数量。例如可以将压缩的最大增量日志配置为4。这意味着在进行 4 次增量写入后,将对数据文件进行压缩并创建更新版本的数据文件。压缩完成后,读取端只需要读取最新的数据文件,而不必关心旧版本文件。
MOR 表的写入行为,依据 index 的不同会有细微的差别:
- 对于 BloomFilter 这种无法对 log file 生成 index 的索引方案,对于 INSERT 消息仍然会写 base file (parquet format),只有 UPDATE 消息会 append log 文件(因为 base file 已经记录了该 UPDATE 消息的 FileGroup ID)。
- 对于可以对 log file 生成 index 的索引方案,例如 Flink writer 中基于 state 的索引,每次写入都是 log format,并且会不断追加和 roll over。
COW 与 MOR 的对比
CopyOnWrite | MergeOnRead | |
---|---|---|
数据延迟 | 高 | 低 |
查询延迟 | 低 | 高 |
Update(I/O) 更新成本 | 高(重写整个 Parquet 文件) | 低(追加到增量日志) |
Parquet 文件大小 | 低(更新成本 I/O 高) | 较大(低更新成本) |
写放大 | 大 | 低(取决于压缩策略) |
查询类型(Query Types)
Hudi 支持如下三种查询类型:
Snapshot Queries
快照查询,可以查询指定 commit/delta commit 即时操作后表的最新快照。在读时合并(MOR)表的情况下,它通过即时合并最新文件片的基本文件和增量文件来提供近实时表(几分钟)。
对于写时复制(COW),它可以替代现有的 parquet 表(或相同基本文件类型的表),同时提供 upsert/delete 和其他写入方面的功能,可以理解为查询最新版本的 Parquet 数据文件。
Incremental Queries
增量查询,可以查询给定 commit/delta commit 即时操作以来新写入的数据。有效的提供变更流来启用增量数据管道。
Read Optimized Queries
读优化查询,可查看给定的 commit/compact 即时操作的表的最新快照。仅将最新文件片的基本/列文件暴露给查询,并保证与非 Hudi 表相同的列查询性能。
Read Optimized Queries 是对 Merge On Read 表类型快照查询的优化。
Snapshot | Read Optimized | |
---|---|---|
数据延迟 | 低 | 高 |
查询延迟 | 高(合并列式基础文件+行式增量日志文件) | 低(原始列式基础文件) |
不同表支持的查询类型
Hudi 表类型定义了如何在 DFS 上索引和布局数据,以及如何在此类组织之上实现上述原语和时间线活动(即如何写入数据)。 反过来,定义基础数据如何向查询公开(即如何读取数据)。
表类型 | 支持的查询类型 |
---|---|
写入时复制 | 快照查询 + 增量查询 |
读取时合并 | 快照查询 + 增量查询 + 读取优化查询 |