Bitset
本主题介绍了在 Milvus 中帮助实现属性过滤和删除操作等关键功能的 bitset 机制。
概述
bitset 是一组位。位是只有两个可能值的元素,最常见的是 0
和 1
,或者布尔值 true
和 false
。在 Milvus 中,bitset 是由位数 0
和 1
组成的数组,可以紧凑而高效地表示特定数据,而不是使用 int、float 或 char。默认情况下,位数是 0
,只有在符合某些条件时才会被设置为 1
。
对 bitset 的操作是基于 布尔逻辑 进行的,输出值要么有效,要么无效,也分别用 1
和 0
表示。例如,逻辑运算符 (opens in a new tab) AND
可用于比较两个 bitset 的同一索引位置上的项,并生成一个以结果为基础的新 bitset。如果两个位置上的项相同,则在新 bitset 中写入 1
;如果不同,则写入 0
。
实现
bitset 是一种简单但强大的机制,可以帮助 Milvus 执行属性过滤、数据删除和时间旅行查询。
属性过滤
由于 bitset 只包含两个可能的值,因此它们非常适合存储 属性过滤 (opens in a new tab) 的结果。符合给定属性过滤条件的数据被标记为 1
。
数据删除
bitset 可用作一种紧凑的方式来存储关于段中的行是否已删除的信息。已删除的实体在相应的 bitset 中标记为 1
,在搜索或查询过程中 不会被计算 (opens in a new tab)。
示例
下面介绍了三个示例,说明了 bitset 在 Milvus 中的使用方式,并涉及到了上面讨论的三种 bitset 的主要实现。在所有三种情况下,都有一个包含 8 个实体的段,然后按照下面显示的顺序进行一系列数据操作语言(DML)事件。
- 当时间戳
ts
等于 100 时,插入了primary_key
为 [1, 2, 3, 4] 的四个实体。 - 当时间戳
ts
等于 200 时,插入了primary_key
为 [5, 6, 7, 8] 的其他四个实体。 - 当时间戳
ts
等于 300 时,删除了primary_key
为 [7, 8] 的实体。 - 只有
primary_key
为 [1, 3, 5, 7] 的实体满足属性过滤的条件。
。
示例一
在这种情况下,用户将 time_travel
设置为 150,这意味着用户对满足 ts = 150
的数据进行查询。图 1 说明了 bitset 生成过程。
在初始过滤阶段,filter_bitset
应该是 [1, 0, 1, 0, 1, 0, 1, 0]
,其中实体 [1, 3, 5, 7] 被标记为 1
,因为它们是有效的过滤结果。
然而,实体 [4, 5, 6, 7] 在 ts
等于 150 时未被插入到向量数据库中。因此,这四个实体应该无论过滤条件如何都被标记为 0。现在,bitset 的结果应该是 [1, 0, 1, 0, 0, 0, 0, 0]
。
如 数据删除 中所讨论的那样,标记为 1
的实体在搜索或查询过程中被忽略。现在需要翻转 bitset 的结果,以便与删除位图进行合并,从而得到 [0, 1, 0, 1, 1, 1, 1, 1]
。
至于删除 bitset 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 将在以下搜索或查询阶段中被计算。
。
示例二
在这种情况下,用户将 time_travel
设置为 250。图 2 说明了 bitset 生成过程。
和示例一一样,初始的 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
二进制逻辑操作符结合起来。result_bitset
的值是 [0, 1, 0, 1, 0, 1, 0, 1]
。也就是说,只有实体 [1, 3, 5, 7] 将在以下搜索或查询阶段中被计算。
。
示例三
在这种情况下,用户将 time_travel
设置为 350。图 3 说明了 bitset 生成过程。
和之前的案例一样,初始的 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
,由于实体 7 和 8 在 ts
= 350 时被删除,因此 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] 将在以下搜索或查询阶段中被计算。
。
下一步
现在你已经了解了 Milvus 中位集的工作原理,你可能还想要:
- 学习如何使用字符串来过滤你的搜索结果,或者参考我们文档中的 混合搜索 (opens in a new tab)。
- 了解在 Milvus 中 数据是如何处理的。