比特集
本主题介绍比特集机制,它有助于在 Milvus 中实现属性过滤和删除操作等关键功能。
概述
比特集是一组比特。比特是只有两个可能值的元素,最典型的是0
和1
,或布尔值true
和false
。在 Milvus 中,比特集是由比特数0
和1
组成的数组,与 ints、浮点数或字符相比,比特集可用于紧凑、高效地表示某些数据。比特数默认为0
,只有在满足特定要求时才会被设置为1
。
对位集的操作采用布尔逻辑,在布尔逻辑下,输出值要么有效要么无效,也分别用1
和0
表示。例如,逻辑运算符 AND
可用于比较两个基于相同索引位置项的比特集,并根据结果生成一个新的比特集。如果某个位置上的两个项目相同,那么在新的比特集中,1
将写入该位置;如果两个项目不同,0
。
实现
Bitset 是一种简单但功能强大的机制,可帮助 Milvus 执行属性过滤、数据删除和时间旅行查询。
属性过滤
由于比特集只包含两个可能的值,因此非常适合存储属性过滤的结果。符合给定属性筛选要求的数据会以1
标记。
数据删除
比特集是存储段中某一行是否被删除的信息的紧凑方式。删除的实体会在相应的比特集中标记为1
,在搜索或查询时不会计算。
示例
下面我们将举出三个例子来说明比特集在 Milvus 中的应用,并参考上文讨论的比特集的所有三种主要实现。在所有三个示例中,都有一个包含 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] 的实体才满足属性筛选条件。
DML 事件的顺序
情况一
在这种情况下,用户将time_travel
设置为 150,这意味着用户对满足ts = 150
的数据进行查询。比特集生成过程如图 1 所示。
在初始过滤阶段,filter_bitset
应该是[1, 0, 1, 0, 1, 0, 1, 0]
,其中实体 [1, 3, 5, 7] 被标记为1
,因为它们是有效的过滤结果。
但是,当ts
等于 150 时,实体 [4, 5, 6, 7] 没有插入向量数据库。因此,无论过滤条件如何,这四个实体都应标记为 0。现在比特集的结果应该是[1, 0, 1, 0, 0, 0, 0, 0]
。
正如在数据删除中所述,在搜索或查询过程中,标记为1
的实体将被忽略。现在需要将比特集结果翻转,以便与删除比特图结合,从而得到[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]
。
现在,经过时间旅行和属性过滤后,我们有两个比特集:filter_bitset
[0, 1, 0, 1, 1, 1, 1, 1]
和del_bitset
[0, 0, 0, 0, 0, 0, 0, 0]
。 将这两个比特集与OR
二进制逻辑运算符相结合。result_bitset 的最终值是[0, 1, 0, 1, 1, 1, 1, 1]
,这意味着在接下来的搜索或查询阶段将只计算实体 1 和 3。
图 1.时间旅行 = 150 时的搜索。
案例二
在这种情况下,用户将time_travel
设置为 250。比特集生成过程如图 2 所示。
与情况一一样,初始filter_bitset
是[1, 0, 1, 0, 1, 0, 1, 0]
。
当ts
= 250 时,所有实体都在向量数据库中。因此,当我们考虑时间戳因素时,filter_bitset
保持不变。同样,我们需要翻转结果,得到[0, 1, 0, 1, 0, 1, 0, 1]
。
至于删除比特集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]
。
现在,经过时间旅行和属性过滤后,我们有两个比特集:filter_bitset
[0, 1, 0, 1, 0, 1, 0, 1]
和del_bitset
[0, 0, 0, 0, 0, 0, 0, 0]
。使用OR
二进制逻辑运算符将这两个比特集合并。结果_比特集是[0, 1, 0, 1, 0, 1, 0, 1]
。也就是说,在接下来的搜索或查询阶段,将只计算实体 [1, 3, 5, 7]。
图 2.时间旅行 = 250 时的搜索
情况三
在这种情况下,用户将time_travel
设置为 350。比特集生成过程如图 3 所示。
与前面的情况一样,初始filter_bitset
是[0, 1, 0, 1, 0, 1, 0, 1]
。
当ts
= 350 时,所有实体都在向量数据库中。因此,最终翻转后的filter_bitset
是[0, 1, 0, 1, 0, 1, 0, 1]
,与案例二相同。
至于删除比特集del_bitset
,由于ts = 350
时已经删除了实体 7 和 8,因此del_bitset
的结果是[0, 0, 0, 0, 0, 0, 1, 1]
。
现在,经过时间旅行和属性过滤后,我们有两个比特集:filter_bitset
[0, 1, 0, 1, 0, 1, 0, 1]
和del_bitset
[0, 0, 0, 0, 0, 0, 1, 1]
。 将这两个比特集与OR
二进制逻辑运算符相结合。最终的result_bitset
是[0, 1, 0, 1, 0, 1, 1, 1]
。也就是说,在接下来的搜索或查询阶段,将只计算实体 [1, 3, 5]。
图 3.时间旅行 = 350 的搜索
下一步
既然你已经知道比特集在 Milvus 中是如何工作的,那么你可能还想