Paimon 删除向量

RowKind 可以标记删除,但它和 DeletionVector(删除向量)是为解决不同场景下的问题而设计的两种机制,它们工作在不同的层面。

简单来说:

  • RowKind 是“逻辑层”的变更指令,主要用于 primary-key 表的 LSM-Tree 合并过程。
  • DeletionVector 是“物理层”的读时过滤优化,用于在不重写数据文件的前提下,快速地“标记”某些行为无效,极大地提升了 DELETE/UPDATE 操作的性能,并使其能应用于所有表类型。

RowKind 是附加在每一行数据上的一个字段,有 +I (INSERT), -U (UPDATE_BEFORE), +U (UPDATE_AFTER), -D (DELETE) 四种类型。

  • 工作机制:它完全依赖于 primary-key 表的 Merge-Tree (LSM) 结构和其合并引擎(Merge Engine)
    • 当执行 DELETE FROM T WHERE pk = 1 时,Paimon 会写入一条 (pk=1, ..., RowKind=-D) 的新记录。
    • 这条 -D 记录和原来的数据记录可能存在于不同的数据文件(不同的 Level)。
    • 只有在读取时或者后台 Compaction(合并)时,Paimon 的合并引擎才会将主键相同的一组记录(比如一个 +I 和一个 -D)放在一起进行计算,最终将这条记录“消除”,使其在查询结果中不可见。
  • 局限性
    1. 必须有主键和合并引擎RowKind 机制只在 primary-key 表中生效,因为它需要根据主键来找到所有相关的记录进行合并。对于没有主键的 Append-Only 表,RowKind 毫无意义。
    2. 读时开销:在 Compaction 发生之前,读取数据需要同时读取多个层级的文件,并在内存中进行合并计算,以判断哪些数据是有效的,这会带来一定的读取开销。
    3. Append-Only 表的难题:对于普通的 Append-Only 表,如果你想删除某一行,是没有办法的。因为没有主键和合并引擎,你无法通过写入 -D 记录来抵消已有的数据。传统的做法是找出包含要删除数据的整个文件,重写这个文件,把要删除的数据剔除掉,这个代价极其高昂。

DeletionVector 的出现:解决性能和普适性问题

DeletionVector 的出现就是为了解决上述 RowKind 的局限性,尤其是非主键表。它是一种Merge-on-Write (MOW) 思想的实现。

  • 工作机制

    1. 定位:当执行 DELETE FROM T WHERE ... 时,Paimon 首先会扫描数据,找到满足条件的行所在的物理位置(即哪个数据文件,以及是文件中的第几行)。
    2. 标记:Paimon 不会重写数据文件,也不会写入 -D 记录。取而代之,它会维护一个位图(Bitmap),这个位图就是删除向量。如果文件 file_A 的第 100 行和第 200 行被删除了,Paimon 就会在这个文件的删除向量中,将第 100 和 200 位标记为 1
    3. 持久化:这个删除向量(位图)会作为一个非常小的独立索引文件DELETION_VECTORS_INDEX)被保存下来。
    4. 读时过滤:当查询数据时,Paimon 会先检查是否存在删除向量索引。如果存在,就会在读取数据文件之前,先加载这个位图。当读取 file_A 时,它会根据位图直接跳过第 100 行和第 200 行的解析,就像它们不存在一样。
  • 优势

    1. 普适性:它不依赖主键和合并引擎,因此可以用于所有表类型,包括 Append-Only 表。这使得 Append-Only 表也具备了高效 DELETE/UPDATE 的能力。
    2. 高性能DELETE 或 UPDATE 操作的开销非常小,因为它只涉及读数据和写一个极小的索引文件,避免了重写庞大数据文件带来的巨大 I/O 开销。
    3. 读取高效:在读取时,只是多了一步加载位图的操作,然后就可以直接跳过无效数据,避免了 RowKind 机制中复杂的内存合并计算。

结论

DeletionVector 并不是要替代 RowKind,而是对 Paimon 更新删除能力的一个巨大增强和优化。它将昂贵的“写时复制/合并”(Copy-on-Write / Merge-on-Read)操作,变成了一个轻量级的“写时标记”(Merge-on-Write),极大地提升了 DELETE/UPDATE 的性能和适用范围,是 Paimon 实现高性能实时湖仓的关键技术之一。

你可能感兴趣的:(Paimon,数据库,大数据,java,数据结构,apache)