【Milvus】索引(Indexes)的概述、分类 和 配置方法_milvus索引
在 Milvus 2.5.10(搭配 pymilvus 2.5.6),索引(Indexes) 是 Milvus 向量数据库中用于加速查询和搜索的关键机制。索引通过对数据(向量字段和标量字段)构建高效的数据结构,显著提升 向量相似性搜索、标量过滤 和 全文检索 的性能。Milvus 支持多种索引类型,针对不同字段类型(如 FLOAT_VECTOR
、SPARSE_FLOAT_VECTOR
、VARCHAR
等)优化查询效率。以下基于 Milvus 2.5.10 的官方文档(https://milvus.io/docs/index.md、https://milvus.io/docs/zh/index-explained.md)和其他相关资源,详细介绍 Milvus 中的索引,包括定义、特性、支持的索引类型、配置方法、代码示例、适用场景和注意事项。
1. 索引概述
索引 是 Milvus 中对集合(Collection)中字段数据预构建的数据结构,旨在加速查询和搜索操作。Milvus 的索引分为两类:
- 向量索引:针对向量字段(如
FLOAT_VECTOR
、SPARSE_FLOAT_VECTOR
),优化相似性搜索(如 ANN,Approximate Nearest Neighbor)。 - 标量索引:针对标量字段(如
INT64
、VARCHAR
、JSON
),加速过滤和精确匹配。
1.1 索引作用
- 加速查询:
- 向量索引:减少向量相似性计算的复杂度(如欧氏距离、余弦相似度)。
- 标量索引:优化范围查询、等值查询和全文检索。
- 提升性能:
- 在大规模数据集中,索引将查询时间从线性扫描(O(n))降至近似对数或常数级别。
- 支持复杂查询:
- 结合向量搜索和标量过滤,实现混合查询(Hybrid Search)。
1.2 索引特性
- 字段级别:索引针对特定字段(如一个
FLOAT_VECTOR
或VARCHAR
字段)创建。 - 类型多样:支持多种索引算法(如
HNSW
、IVF_FLAT
、INVERTED
),适配不同场景。 - 异步构建:索引构建是异步操作,可在后台完成。
- 不可更改:索引创建后不可修改,需删除后重建。
- 存储开销:索引会增加存储需求,需权衡性能和存储。
2. 支持的索引类型
Milvus 2.5.10 支持以下索引类型,分为 向量索引 和 标量索引,每种类型针对特定字段和查询场景优化。
2.1 向量索引
向量索引用于加速向量相似性搜索,适用于 FLOAT_VECTOR
、BINARY_VECTOR
、FLOAT16_VECTOR
、BFLOAT16_VECTOR
和 SPARSE_FLOAT_VECTOR
字段。以下是主要向量索引类型(参考 https://milvus.io/docs/index.md):
密集向量索引(FLOAT_VECTOR
等)
- HNSW(Hierarchical Navigable Small World):
- 描述:基于图结构的索引,适合高精度 ANN 搜索。
- 参数:
M
:每个节点的出边数(4-64,影响精度和存储)。efConstruction
:构建时的搜索范围(8-512,影响构建速度)。ef
:搜索时的动态参数(影响查询速度)。
- 适用场景:高精度搜索,中小规模数据集(百万级)。
- 优点:高召回率,适合余弦相似度(
COSINE
)和欧氏距离(L2
)。 - 缺点:内存占用高,构建时间长。
- IVF_FLAT(Inverted File with Flat):
- 描述:基于聚类的索引,将向量分到多个簇(Cluster)。
- 参数:
nlist
:簇数量(影响构建时间和查询精度)。nprobe
:搜索时检查的簇数(1-nlist
,影响速度和精度)。
- 适用场景:大规模数据集(亿级),高吞吐量。
- 优点:存储开销低,适合大集群。
- 缺点:精度低于 HNSW,需调优
nprobe
。
- IVF_SQ8(Scalar Quantization):
- 描述:基于量化的 IVF 索引,压缩向量数据。
- 参数:同
IVF_FLAT
。 - 适用场景:内存受限场景。
- 优点:存储效率高。
- 缺点:精度略低。
- IVF_PQ(Product Quantization):
- 描述:将向量分段并量化,进一步压缩。
- 参数:
nlist
、nprobe
:同IVF_FLAT
。m
:子空间数量(影响压缩率)。
- 适用场景:超大规模数据,内存严格受限。
- 优点:极高压缩率。
- 缺点:精度损失较大。
- FLAT:
- 描述:不构建索引,直接暴力搜索。
- 适用场景:小数据集(<10,000),需要绝对精确结果。
- 优点:最高精度,无索引开销。
- 缺点:查询速度慢,O(n) 复杂度。
稀疏向量索引(SPARSE_FLOAT_VECTOR
)
- AUTOINDEX:
- 描述:专为稀疏向量设计的索引,优化 BM25 全文检索。
- 参数:
metric_type=\"BM25\"
:使用 BM25 算法。
- 适用场景:全文检索、RAG(Retrieval-Augmented Generation)。
- 优点:高效支持关键词搜索,稀疏表示节省存储。
- 缺点:依赖分词质量,仅限 BM25 场景。
- 要求:需配合
FunctionType.BM25
函数将文本转换为稀疏向量。
二进制向量索引(BINARY_VECTOR
)
- HNSW 和 FLAT:支持二进制向量的相似性搜索(
HAMMING
或JACCARD
距离)。
2.2 标量索引
标量索引用于加速标量字段(如 INT64
、VARCHAR
、JSON
)的过滤和查询。以下是主要标量索引类型:
- INVERTED(倒排索引):
- 适用字段:
BOOL
、INT8
、INT16
、INT32
、INT64
、FLOAT
、DOUBLE
、VARCHAR
、JSON
。 - 描述:构建倒排索引,快速查找包含特定值的记录。
- 参数(
JSON
字段):json_path
:指定 JSON 键(如metadata[\"category\"]
)。json_cast_type
:目标类型(如\"varchar\"
)。
- 适用场景:
- 精确匹配(如
category == \"electronics\"
)。 - 全文检索(
TEXT_MATCH
表达式)。 - JSON 字段过滤。
- 精确匹配(如
- 优点:高效支持等值和范围查询。
- 缺点:存储开销随唯一值增加。
- 适用字段:
- TRIE(前缀树):
- 适用字段:
VARCHAR
。 - 描述:基于前缀树的索引,优化字符串前缀匹配。
- 适用场景:前缀查询(如
LIKE \"abc%\"
)。 - 优点:高效支持前缀搜索。
- 缺点:仅限前缀匹配,功能单一。
- 适用字段:
- STL_SORT(标准模板库排序):
- 适用字段:
BOOL
、INT8
、INT16
、INT32
、INT64
、FLOAT
、DOUBLE
。 - 描述:基于排序的索引,优化范围查询。
- 适用场景:范围查询(如
price > 100
)。 - 优点:简单高效。
- 缺点:仅支持排序字段。
- 适用字段:
- BITMAP:
- 适用字段:
BOOL
、INT8
、INT16
、INT32
、INT64
、FLOAT
、DOUBLE
、VARCHAR
。 - 描述:基于位图的索引,优化高基数字段的等值查询。
- 适用场景:高频等值查询(如
category == \"electronics\"
)。 - 优点:低存储开销。
- 缺点:范围查询效率较低。
- 适用字段:
- JSON In-Memory Index:
- 适用字段:
JSON
。 - 描述:内存中的倒排索引,优化 JSON 字段查询。
- 适用场景:频繁的 JSON 键值查询。
- 优点:高性能。
- 缺点:内存占用高。
- 适用字段:
2.3 索引支持的度量类型
- 密集向量:
L2
(欧氏距离)IP
(内积)COSINE
(余弦相似度)
- 稀疏向量:
BM25
(全文检索相关性评分)
- 二进制向量:
HAMMING
(汉明距离)JACCARD
(杰卡德距离)
3. 索引配置方法
在 Milvus 2.5.10 中,索引通过 MilvusClient.prepare_index_params()
和 client.create_index()
配置。以下是配置步骤和代码示例。
3.1 配置步骤
- 定义 Schema:
- 指定字段类型(向量或标量)和约束。
- 对于全文检索,添加
FunctionType.BM25
函数。
- 创建索引参数:
- 使用
MilvusClient.prepare_index_params()
。 - 通过
add_index
添加索引配置(字段、类型、参数)。
- 使用
- 构建索引:
- 调用
client.create_index()
,异步构建索引。
- 调用
- 加载集合:
- 使用
client.load_collection()
加载索引到内存。
- 使用
3.2 代码示例:综合索引配置
以下示例展示如何为密集向量(FLOAT_VECTOR
)、稀疏向量(SPARSE_FLOAT_VECTOR
)、标量字段(VARCHAR
、JSON
)创建索引,结合全文检索、文本匹配和混合搜索。
from pymilvus import MilvusClient, DataType, AnnSearchRequest, RRFRanker, FunctionType, Functionfrom pymilvus.client.constants import ConsistencyLevelimport random# 连接 Milvusclient = MilvusClient(uri=\"http://localhost:19530\")try: # 创建数据库 client.create_database(db_name=\"test_db\") client.use_database(db_name=\"test_db\") # 创建 Schema schema = MilvusClient.create_schema(auto_id=True) schema.add_field( field_name=\"pk\", datatype=DataType.VARCHAR, is_primary=True, auto_id=True, max_length=100 ) schema.add_field( field_name=\"content\", datatype=DataType.VARCHAR, max_length=65535, enable_analyzer=True, enable_match=True, analyzer_params={\"type\": \"english\"} ) schema.add_field(field_name=\"sparse_vector\", datatype=DataType.SPARSE_FLOAT_VECTOR) schema.add_field(field_name=\"dense_vector\", datatype=DataType.FLOAT_VECTOR, dim=128) schema.add_field(field_name=\"metadata\", datatype=DataType.JSON) # 定义 BM25 函数 bm25_function = Function( name=\"content_bm25_sparse\", input_field_names=[\"content\"], output_field_names=[\"sparse_vector\"], function_type=FunctionType.BM25 ) schema.add_function(bm25_function) # 创建集合 client.create_collection( collection_name=\"index_collection\", schema=schema, consistency_level=ConsistencyLevel.Session ) # 创建索引 index_params = MilvusClient.prepare_index_params() # 稀疏向量索引(全文检索) index_params.add_index( field_name=\"sparse_vector\", index_type=\"AUTOINDEX\", metric_type=\"BM25\" ) # 密集向量索引(语义搜索) index_params.add_index( field_name=\"dense_vector\", index_type=\"HNSW\", metric_type=\"COSINE\", params={\"M\": 16, \"efConstruction\": 200} ) # 标量索引(文本匹配) index_params.add_index( field_name=\"content\", index_type=\"INVERTED\" ) # JSON 索引 index_params.add_index( field_name=\"metadata\", index_type=\"INVERTED\", index_name=\"json_category\", params={\"json_path\": \"metadata[\\\"category\\\"]\", \"json_cast_type\": \"varchar\"} ) client.create_index(collection_name=\"index_collection\", index_params=index_params) # 插入数据 data = [ { \"content\": \"Milvus supports hybrid search with BM25 and dense vectors.\", \"dense_vector\": [random.random() for _ in range(128)], \"metadata\": {\"category\": \"database\"} }, { \"content\": \"AI applications benefit from vector databases.\", \"dense_vector\": [random.random() for _ in range(128)], \"metadata\": {\"category\": \"AI\"} } ] client.insert(collection_name=\"index_collection\", data=data) # 加载集合 client.load_collection(collection_name=\"index_collection\") # 混合搜索 query_text = \"vector database\" dense_query_vector = [random.random() for _ in range(128)] sparse_request = AnnSearchRequest( data=[query_text], anns_field=\"sparse_vector\", param={\"metric_type\": \"BM25\"}, limit=2, expr=\"TEXT_MATCH(content, \'vector\') and metadata[\\\"category\\\"] == \\\"database\\\"\" ) dense_request = AnnSearchRequest( data=[dense_query_vector], anns_field=\"dense_vector\", param={\"metric_type\": \"COSINE\", \"params\": {\"ef\": 64}}, limit=2 ) results = client.hybrid_search( collection_name=\"index_collection\", reqs=[sparse_request, dense_request], ranker=RRFRanker(), limit=2, output_fields=[\"content\", \"metadata\"], consistency_level=ConsistencyLevel.Strong ) print(\"Hybrid search results:\") for result in results[0]: print(f\"Document: {result[\'entity\'][\'content\']}, Metadata: {result[\'entity\'][\'metadata\']}, Score: {result[\'distance\']}\")except Exception as e: print(f\"Error: {e}\")finally: # 清理 client.drop_collection(collection_name=\"index_collection\") client.drop_database(db_name=\"test_db\")
输出示例
Hybrid search results:Document: Milvus supports hybrid search with BM25 and dense vectors., Metadata: {\'category\': \'database\'}, Score: 0.912Document: AI applications benefit from vector databases., Metadata: {\'category\': \'AI\'}, Score: 0.745
代码说明
- Schema:
- 包含
pk
(主键)、content
(VARCHAR
,支持全文检索和文本匹配)、sparse_vector
(BM25)、dense_vector
(语义搜索)、metadata
(JSON
)。 - 添加
FunctionType.BM25
函数,将content
转换为sparse_vector
。
- 包含
- 索引:
sparse_vector
:AUTOINDEX
(BM25)。dense_vector
:HNSW
(COSINE)。content
:INVERTED
(文本匹配)。metadata
:INVERTED
(JSON 键值查询)。
- 混合搜索:
- 稀疏向量搜索:BM25,结合
TEXT_MATCH
和 JSON 过滤。 - 密集向量搜索:HNSW,COSINE 度量。
- 使用
RRFRanker
融合结果。
- 稀疏向量搜索:BM25,结合
4. 索引选择建议
选择索引类型时,需权衡数据规模、查询需求和资源限制:
4.1 向量索引选择
- HNSW:
- 适合:中小规模数据集(<10M),高精度要求(如推荐系统)。
- 参数建议:
M=16
,efConstruction=200
,ef=64
。
- IVF_FLAT:
- 适合:大规模数据集(>10M),高吞吐量(如搜索引擎)。
- 参数建议:
nlist=1024
,nprobe=10-100
。
- IVF_SQ8/IVF_PQ:
- 适合:内存受限场景(嵌入式设备)。
- 参数建议:
m=16
(PQ),nprobe=10
。
- FLAT:
- 适合:小数据集(<10K),绝对精确(如学术实验)。
- AUTOINDEX:
- 适合:全文检索(BM25),稀疏向量场景。
- 要求:配合
FunctionType.BM25
。
4.2 标量索引选择
- INVERTED:
- 适合:等值查询、全文检索、JSON 字段过滤。
- 示例:
category == \"electronics\"
,TEXT_MATCH(content, \'AI\')
。
- TRIE:
- 适合:前缀查询(如
LIKE \"abc%\"
)。
- 适合:前缀查询(如
- STL_SORT:
- 适合:范围查询(如
price > 100
)。
- 适合:范围查询(如
- BITMAP:
- 适合:高基数字段的等值查询。
4.3 索引优化
- 数据规模:大数据集优先
IVF_FLAT
或IVF_PQ
,小数据集用HNSW
或FLAT
。 - 查询模式:频繁等值查询用
INVERTED
,前缀查询用TRIE
。 - 存储限制:压缩索引(如
IVF_SQ8
)适合内存受限环境。 - 混合查询:为向量和标量字段都创建索引,支持复杂过滤。
5. 注意事项
- 版本兼容性:
- 确保使用 Milvus 2.5.10 和
pymilvus
2.5.6(pip show pymilvus
)。 AUTOINDEX
和 BM25 功能在 2.5.x 中稳定支持。
- 确保使用 Milvus 2.5.10 和
- 索引限制:
- 每个字段只能有一种索引类型。
- 索引创建后不可修改,需删除后重建。
- 性能影响:
- 索引构建耗时,建议异步构建(
async_=True
)。 - 索引增加存储开销,评估数据规模和字段基数。
- 索引构建耗时,建议异步构建(
- 错误处理:
- 确保字段类型与索引类型匹配(如
SPARSE_FLOAT_VECTOR
只支持AUTOINDEX
)。 - 示例:
try: client.create_index(...)except Exception as e: print(f\"Error: {e}\")
- 确保字段类型与索引类型匹配(如
- 已知问题:
- 早期版本(如 2.5.0-beta)中
AUTO_INDEX
可能导致错误,2.5.10 已修复(https://milvus.io/docs/index.md)。
- 早期版本(如 2.5.0-beta)中
6. 总结
Milvus 2.5.10 的索引(Indexes) 是加速向量和标量查询的核心机制,支持密集向量(HNSW
、IVF_FLAT
)、稀疏向量(AUTOINDEX
)和标量字段(INVERTED
、TRIE
)的多种索引类型。向量索引优化相似性搜索,标量索引加速过滤和全文检索,结合分析器和 BM25 实现高效的混合搜索。