跳到主要内容
版本:v3.0.x

Bitset

本主题介绍 Bitset 机制,它有助于在 Milvus 中实现属性过滤和 删除操作 等关键功能。

概述

Bitset 是一组比特。比特是只有两种可能值的元素,最典型的是 01,或布尔值 truefalse。在 Milvus 中,Bitset 是由比特数 01 组成的数组,与 ints、浮点数或字符相比,它可以用来紧凑、高效地表示某些数据。比特数默认为 0,只有在满足特定要求时才会被设置为 1

对位集的操作采用 布尔逻辑,在 布尔逻辑 下,输出值要么有效要么无效,也分别用 10 表示。例如,逻辑运算符 AND 可用于根据相同索引位置的项对两个 Bitset 进行比较,并根据结果生成一个新的 Bitset。如果某个位置上的两个项目相同,那么在新的 Bitset 中,1 将被写入该位置;如果两个项目不同,0

实现

Bitset 是一种简单而强大的机制,可帮助 Milvus 执行属性过滤、数据删除和使用时空旅行进行查询。

属性过滤

由于 Bitset 只包含两个可能的值,因此非常适合用来存储 属性筛选 的结果。符合给定属性筛选要求的数据会以 1 标记。

数据删除

Bitset 是存储段中某一行是否被删除的信息的简洁方式。删除的实体会在相应的 Bitset 中标记为 1,在搜索或查询时 不会计算

示例

下面我们将举出三个例子来说明 Bitset 在 Milvus 中的应用,并参考上文讨论的 Bitset 的所有三种主要实现。在所有三个示例中,都有一个包含 8 个实体的段,然后按照下图所示的顺序发生一系列数据操作语言(DML)事件。

  • 其中四个实体(其 primary_key s 分别为 [1、2、3、4])在时间戳 ts 等于 100 时插入。
  • 其余四个实体(其 primary_key s 分别为 [5、6、7、8])在时间戳 ts 等于 200 时插入。
  • 当时间戳 ts 等于 300 时,删除 primary_key s 为 [7, 8] 的实体。
  • 只有 primary_key s 为 [1, 3, 5, 7] 的实体才满足属性筛选条件。

Order of DML events

情况一

在这种情况下,用户将 time_travel 设置为 150,这意味着用户对满足 ts = 150 的数据进行查询。Bitset 生成过程如图 1 所示。

在初始过滤阶段,filter_bitset 应该是 [1, 0, 1, 0, 1, 0, 1, 0],其中实体 [1, 3, 5, 7] 被标记为 1,因为它们是有效的过滤结果。

但是,当 ts 等于 150 时,实体 [4, 5, 6, 7] 没有插入向量数据库。因此,无论过滤条件如何,这四个实体都应标记为 0。现在 Bitset 的结果应该是 [1, 0, 1, 0, 0, 0, 0, 0]

正如在 数据删除 中所述,在搜索或查询过程中,标记为 1 的实体将被忽略。现在需要将 Bitset 结果翻转,以便与删除比特图结合,从而得到 [0, 1, 0, 1, 1, 1, 1, 1]

至于删除位集 del_bitset,初始值应该是 [0, 0, 0, 0, 0, 0, 1, 1]。但是,实体 7 和实体 8 在 ts 为 300 时才会删除。因此,当 ts 为 150 时,实体 7 和 8 仍然有效。因此,"时间旅行 "后的 del_bitset 值为 [0, 0, 0, 0, 0, 0, 0, 0]

现在,经过时间旅行和属性过滤后,我们有两个 Bitset:filter_bitset [0, 1, 0, 1, 1, 1, 1, 1]del_bitset [0, 0, 0, 0, 0, 0, 0, 0]。 将这两个 Bitset 与 OR 二进制逻辑运算符相结合。result_bitset 的最终值是 [0, 1, 0, 1, 1, 1, 1, 1],这意味着在接下来的搜索或查询阶段,将只计算实体 1 和 3。

Figure 1. Search with Time Travel = 150.

案例二

在这种情况下,用户将 time_travel 设置为 250。Bitset 生成过程如图 2 所示。

与情况一一样,初始 filter_bitset[1, 0, 1, 0, 1, 0, 1, 0]

ts = 250 时,所有实体都在向量数据库中。因此,当我们考虑时间戳因素时,filter_bitset 保持不变。同样,我们需要翻转结果,得到 [0, 1, 0, 1, 0, 1, 0, 1]

至于删除 Bitset del_bitset,初始值是 [0, 0, 0, 0, 0, 0, 1, 1]。但是,实体 7 和实体 8 在 ts 为 300 时才被删除。因此,当 ts 为 250 时,实体 7 和 8 仍然有效。因此,"时间旅行 "后的 del_bitset[0, 0, 0, 0, 0, 0, 0, 0]

现在,经过时间旅行和属性过滤后,我们有两个 Bitset:filter_bitset [0, 1, 0, 1, 0, 1, 0, 1]del_bitset [0, 0, 0, 0, 0, 0, 0, 0]。将这两个 Bitset 与 OR 二进制逻辑运算符相结合。结果_Bitset 是 [0, 1, 0, 1, 0, 1, 0, 1]。也就是说,在接下来的搜索或查询阶段,将只计算实体 [1, 3, 5, 7]。

Figure 2. Search with Time Travel = 250.

情况三

在这种情况下,用户将 time_travel 设置为 350。Bitset 生成过程如图 3 所示。

与前面的情况一样,初始 filter_bitset[0, 1, 0, 1, 0, 1, 0, 1]

ts= 350 时,所有实体都在向量数据库中。因此,最终翻转后的 filter_bitset[0, 1, 0, 1, 0, 1, 0, 1],与案例二相同。

至于删除 Bitset del_bitset,由于 ts = 350 时已经删除了实体 7 和 8,因此 del_bitset 的结果是 [0, 0, 0, 0, 0, 0, 1, 1]

现在,经过时间旅行和属性过滤后,我们有两个 Bitset:filter_bitset [0, 1, 0, 1, 0, 1, 0, 1]del_bitset [0, 0, 0, 0, 0, 0, 1, 1]。 将这两个 Bitset 与 OR 二进制逻辑运算符相结合。最终的 result_bitset[0, 1, 0, 1, 0, 1, 1, 1]。也就是说,在接下来的搜索或查询阶段,将只计算实体 [1, 3, 5]。

Figure 3. Search with Time Travel = 350.

下一步

既然知道了 Bitset 在 Milvus 中的工作原理,你可能还想