🚀 免费试用 Zilliz Cloud,完全托管的 Milvus,体验 10 倍的性能提升!立即试用>

milvus-logo
LFAI
  • Home
  • Blog
  • Bitset 如何实现向量相似性搜索的多功能性

Bitset 如何实现向量相似性搜索的多功能性

  • Engineering
February 14, 2022
Yudong Cai

Bitset Cover Image Bitset 封面图片

作者:蔡玉东倪安琪

随着 Milvus 2.0 的发布,矢量数据库的各种新的基本功能也一并推出。在这些新功能中,时间旅行、属性过滤和删除操作是相关联的,因为这三个功能是通过一个共同的机制--比特集--来实现的。

因此,本文旨在阐明 Milvus 中比特集的概念,并通过三个例子解释它是如何支持删除操作、时间旅行和属性过滤的。

什么是比特集?

比特集是由比特数("0 "和 "1")组成的数组,可用来表示某些数据信息。与用 Ints、floats 或 chars 存储数据相比,使用比特集可以紧凑、高效地存储某些类型的数据。比特集基于布尔逻辑工作,根据布尔逻辑,输出值要么有效要么无效,通常分别用 "1 "和 "0 "表示。1 "代表有效,"0 "代表无效。由于比特集具有很高的效率,可以节省存储空间,因此还可以用来实现属性过滤、删除操作、时间旅行等多种功能。

从 0.7.0 版开始,为了实现删除功能,Milvus 引入了 bitset 的概念。更具体地说,比特集用于标记段中的每一行是否被删除。已删除的实体在相应的比特集中标记为 "1",因此在搜索或查询时将不会计算已删除的实体。

在 Milvus 2.0 版本中,比特集的应用得到了扩展,可以实现更多的功能,如属性过滤和时间旅行。比特集的一般原则保持不变。也就是说,如果一个实体在相应的比特集中被标记为 "1",那么在搜索或查询时该实体将被忽略。在 Milvus 中,比特集用于实现 3 个功能:

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

比特集在 Milvus 中是如何工作的?

下面的示例用于说明比特集在 Milvus 中的工作原理。

前提条件

假设有一个包含八个实体的段,一系列数据操作语言(DML)事件按下图所示顺序发生。

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

DML events DML 事件

案例一

假设用户为time_travel 设置的值是 150。换句话说,当ts = 150 时,用户对存储在 Milvus 中的数据进行查询。比特集生成过程如图 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]。由于在 Milvus 中,比特集计算的一般原则是在搜索或查询过程中忽略比特集中标记为 "1 "的实体,因此时间旅行和属性过滤后的比特集结果需要翻转,以便与删除比特图相结合。filter_bitset 的翻转结果应为 [0,1,0,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] 和del_bitset [0,0,0,0,0,0,0]。 用二进制逻辑操作符 "OR "组合这两个比特集。result_bitset 的最终值是 [0,1,0,1,1,1,1]。也就是说,在接下来的搜索或查询阶段,将只计算实体 1 和实体 3。

Figure 1 图 1

案例二

假设用户为time_travel 设置的值是 250。换句话说,当ts = 250 时,用户对存储在 Milvus 中的数据进行查询。比特集生成过程如图 2 所示。

与第一种情况一样,初始属性过滤阶段的结果filter_bitset 应该是[1, 0, 1, 0, 1, 0, 1, 0]。

ts= 250 时,所有实体 [1, 2, 3, 4, 5, 6, 7, 8] 都被插入到向量数据库中。因此,之前filter_bitset 的结果保持不变。同样,我们需要翻转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]。 用二进制逻辑操作符 "OR "组合这两个比特集。result_bitset 的最终值是 [0,1,0,1,0,1,0,1]。也就是说,在接下来的搜索或查询阶段,将只计算实体 [1, 3, 5, 7]。

Figure 2 图 2

案例三

假设用户为time_travel 设置的值是 350。换句话说,当ts = 350 时,用户对存储在 Milvus 中的数据进行查询。比特集生成过程如图 3 所示。

与情况一和情况二相同,初始属性过滤阶段的结果filter_bitset 是 [0, 1, 0, 1, 0, 1, 0, 1]。

ts= 350 时,所有实体 [1, 2, 3, 4, 5, 6, 7, 8] 都被插入到向量数据库中。因此,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, 3, 5]。

Figure 3 图 3

下一步是什么?

在 2.0 新功能系列博客中,我们将介绍新功能的设计。阅读本系列博客的更多内容!

Try Managed Milvus for Free

Zilliz Cloud is hassle-free, powered by Milvus and 10x faster.

Get Started

Like the article? Spread the word

扩展阅读