干货分享|Bitset 应用详解

2022-03-08 13:35:27 浏览数 (2)

✏️ 编者按:

Milvus 2.0 带来了不少新功能。在这些新功能中,时间旅行(time travel)、属性过滤和删除操作相互关联,因为这三个功能是通过共同的机制——Bitset 来实现的。Milvus 研发工程师蔡宇东将为大家介绍 Milvus 中 Bitset 的应用,并通过三个例子详细解释它是如何支持删除操作、时间旅行和属性过滤的。

什么是 Bitset?

从 Milvus 0.7.0 版本开始,为了支持 Delete 功能,我们引入了 Bitset,用于标记 segment 中的每行 entity 是否已被删除(若 Bitset 对应的 bit 位为 1,表明该行 entity 已被删除,该行 entity 在查询时不参与运算)。

在 Milvus 2.0 版本,我们进一步扩展了 Bitset 的使用。Bitset 最基本的语义保持不变——若对应的 bit 位为 1,表明该行 entity 不参与查询运算。但 Bitset 的使用不再局限于 Delete 操作,有 3 种操作会影响 Bitset,它们分别是:

  • 属性过滤
  • 数据删除
  • 时间旅行

在 Milvus 中,Bitset 是如何计算的?

接下来,我们用三个例子来说明 Bitset 是如何计算的。

假设有 1 个 segment ,我们对这个 segment 依次执行了 3 次 DML(data manipulation language)操作:

Order of DML events

  • ts = 100 时,执行插入操作,插入了 4 条 entity,它们的 primary_keys 分别为 [1, 2, 3, 4];
  • ts = 200 时,执行第二次插入操作,插入另外 4 条 entity,它们的 primary_keys 分别为 [5, 6, 7, 8];
  • ts = 300 时,执行 Delete 操作,删除了 2 条 entity,它们的 primary_key 分别为 [7, 8]

同时假设在进行查询时,通过属性过滤得到的结果为 primary_key = [1, 3, 5, 7]

案例一

Search with time_traval = 150

假设用户执行第一次查询,指定time_travel = 150。Bitset 的计算过程如上图所示。

filter_bitset 初始状态为 [1, 0, 1, 0, 1, 0, 1, 0] (此时 bit 位为 1 表示有效),因为查询时指定的 time_travel = 150,该时刻 pk = [5, 6, 7, 8] 的 entity 还没有插入,所以 pk = [5, 6, 7, 8] 的 entity 在 Bitset 中对应 bit 位都要清零。计算得到 filter_bitset_2 = [1, 0, 1, 0, 0, 0, 0, 0]。又因为最终结果 bitset 中的 1 应该表示该行 entity 无效,所以需要对 filter_bitset_2 中所有 bit 位取反,得到 filter_bitset_3 = [0, 1, 0, 1, 1, 1, 1, 1]

del_bitset 初始状态为 [0, 0, 0, 0, 0, 0, 1, 1],考虑查询时指定的 time_travel = 150,该时刻 delete 操作还没有执行,所以 Bitset 所有 bit 位都应该清零,表示所有的数据都是有效的。这样就得到了 del_bitset_2 = [0, 0, 0, 0, 0, 0, 0, 0]

filter_bitset_3del_bitset_2 进行 OR 操作,可得到最终 result_bitset = [0, 1, 0, 1, 1, 1, 1, 1]

最终,我们会用 result_bitset 去参与查询运算。

案例二

Search with time_traval = 250

假设用户执行第二次查询,指定time_travel = 250。Bitset 的计算过程如上图所示。

与第一个案例一样,filter_bitset 初始状态应该是 [1, 0, 1, 0, 1, 0, 1, 0]。

当 ts = 250 时,所有 entity [1, 2, 3, 4, 5, 6, 7, 8] 已经被插入到 Milvus 中。因此,filter_bitset_2和之前 filter_bitset 的结果保持不变。同样,我们要对 filter_bitset_2的所有 bit 位取反,得到 [0, 1, 0, 1, 0, 1, 0, 1]。

del_bitset 初始状态为 [0, 0, 0, 0, 0, 1, 1]。同样考虑查询时指定的 time_travel = 250,该时刻 delete 操作还没有执行,所以 Bitset 所有 bit 位都应该清零,表示所有的数据都是有效的。因此,time travel 后的del_bitset_2 = [0, 0, 0, 0, 0, 0, 0]

filter_bitset_3del_bitset_2 进行 OR 操作,可得到最终 result_bitset = [0, 1, 0, 1, 0, 1, 0, 1]

最终只有 entities [1, 3, 5, 7] 会参与之后的查询运算。

案例三

假设用户执行第三次查询,指定time_travel = 350。那么,Bitset 的计算过程是什么样的?参考上方两个案例进行思考,点击下方的空白显示提示。

你想对了吗?

0 人点赞