标量索引
Milvus 支持结合标量和向量字段的过滤搜索。为了提高涉及标量字段搜索的效率,Milvus 从 2.1.0 版本开始引入了标量字段索引。本文概述了 Milvus 中的标量字段索引,帮助您了解其重要性和实现。
概述
在 Milvus 中进行向量相似性搜索时,您可以使用逻辑运算符将标量字段组织成布尔表达式。
当 Milvus 收到带有这种布尔表达式的搜索请求时,它会将布尔表达式解析为抽象语法树(AST)来生成属性过滤的物理计划。然后 Milvus 在每个 segment 中应用物理计划来生成位集作为过滤结果,并将结果作为向量搜索参数包含在内以缩小搜索范围。在这种情况下,向量搜索的速度在很大程度上依赖于属性过滤的速度。
标量字段索引是通过以特定方式对标量字段值进行排序来确保属性过滤速度以加速信息检索的一种方法。
标量字段索引算法
Milvus 旨在通过其标量字段索引算法实现低内存使用、高过滤效率和短加载时间。这些算法分为两种主要类型:自动索引和倒排索引。
自动索引
Milvus 提供 AUTOINDEX
选项,使您无需手动选择索引类型。调用 create_index
方法时,如果未指定 index_type
,Milvus 会根据数据类型自动选择最合适的索引类型。
下表列出了 Milvus 支持的数据类型及其对应的自动索引算法。
数据类型 | 自动索引算法 |
---|---|
VARCHAR | 倒排索引 |
INT8 | 倒排索引 |
INT16 | 倒排索引 |
INT32 | 倒排索引 |
INT64 | 倒排索引 |
FLOAT | 倒排索引 |
DOUBLE | 倒排索引 |
倒排索引
倒排索引提供了一种灵活的方式,通过手动指定索引参数为标量字段创建索引。这种方法适用于各种场景,包括点查询、模式匹配查询、全文搜索、JSON 搜索、布尔搜索,甚至前缀匹配查询。
Milvus 中实现的倒排索引由 Tantivy 提供支持,这是一个全文搜索引擎库。Tantivy 确保 Milvus 中的倒排索引既高效又快速。
倒排索引有两个主要组件:词典和倒排列表。词典包括按字母顺序排序的所有标记化单词,而倒排列表包含每个单词出现的文档列表。这种设置使点查询和范围查询比暴力搜索更快、更高效。
使用倒排索引的优势在以下操作中特别明显:
- 点查询:例如,当搜索包含单词 Milvus 的文档时,过程首先检查词典中是否存在 Milvus。如果未找到,则没有文档包含该单词。但是,如果找到了,则检索与 Milvus 关联的倒排列表,指示包含该单词的文档。这种方法比在一百万个文档中进行暴力搜索要高效得多,因为排序的词典显著降低了找到单词 Milvus 的时间复杂度。
- 范围查询:范围查询的效率,例如查找按字母顺序大于 very 的单词的文档,也通过排序的词典得到增强。这种方法比暴力搜索更高效,提供更快、更准确的结果。
测试结果
为了演示 Milvus 中标量索引提供的性能改进,进行了一项实验,比较了使用倒排索引和对原始数据进行暴力搜索的几个表达式的性能。
实验涉及在两种条件下测试各种表达式:使用倒排索引和使用暴力搜索。为了确保公平性,在测试中保持相同的数据分布,每次使用相同的 Collection。在每次测试之前,释放 Collection,删除并重建索引。此外,在每次测试之前执行热查询以最小化冷热数据的影响,每个查询执行多次以确保准确性。
对于 100 万条记录的数据集,使用倒排索引可以为点查询提供高达 30 倍的性能改进。对于更大的数据集,性能增益可能更加显著。
性能建议
为了充分利用 Milvus 在标量字段索引方面的能力并在向量相似性搜索中释放其潜力,您可能需要一个模型来根据您拥有的数据估算所需的内存大小。
下表列出了 Milvus 支持的所有数据类型的估算函数。
-
数值字段
数据类型 内存估算函数(MB) INT8 numOfRows * 12 / 1024 / 1024 INT16 numOfRows * 12 / 1024 / 1024 INT32 numOfRows * 12 / 1024 / 1024 INT64 numOfRows * 24 / 1024 / 1024 FLOAT32 numOfRows * 12 / 1024 / 1024 DOUBLE numOfRows * 24 / 1024 / 1024 -
字符串字段
字符串长度 内存估算函数(MB) (0, 8] numOfRows * 128 / 1024 / 1024 (8, 16] numOfRows * 144 / 1024 / 1024 (16, 32] numOfRows * 160 / 1024 / 1024 (32, 64] numOfRows * 192 / 1024 / 1024 (64, 128] numOfRows * 256 / 1024 / 1024 (128, 65535] numOfRows * strLen * 1.5 / 1024 / 1024