Milvus 的索引

发布于:2025-03-17 ⋅ 阅读:(20) ⋅ 点赞:(0)

1. Milvus 索引类型详细介绍

1.1 FLAT 索引
  • 特点:FLAT 是最简单直接的索引方式,它直接存储原始向量数据,不做任何压缩或转换。在搜索时,会对集合中的所有向量进行遍历,计算其与查询向量的相似度。
  • 优点
    • 搜索结果精确,能保证 100% 的召回率,因为会遍历所有向量。
    • 无需额外的索引构建过程,插入数据后可立即进行搜索,使用简单。
  • 缺点
    • 搜索效率极低,随着数据量的增加,搜索时间会呈线性增长,性能较差。
  • 适用场景
    • 数据量较小的场景,对搜索效率要求不高,但对结果准确性要求极高。
    • 用于验证其他索引类型的搜索结果准确性。
  • search 参数示例
search_params = {
    "metric_type": "L2",  # 距离度量类型,这里使用欧氏距离
    "params": {}
}
1.2 IVF(Inverse File Index)索引
  • 特点:将整个向量空间划分为多个簇(倒排表),每个簇有一个质心向量。搜索时,先找出与查询向量最接近的几个簇,然后只在这些簇内进行向量搜索。
  • 优点
    • 相比 FLAT 索引,搜索效率显著提高,尤其是在大规模数据场景下,通过缩小搜索范围减少计算量。
    • 可以通过调整簇的数量(nlist)和搜索时访问的簇数量(nprobe)来平衡搜索精度和速度。
  • 缺点
    • 搜索结果是近似的,存在一定的召回率损失。
    • 需要额外的时间和空间来构建索引,计算簇的质心向量。
  • 适用场景
    • 大规模数据的向量搜索场景,对搜索效率有一定要求,能接受一定的召回率损失。
    • 适用于大多数实际应用,如图像检索、推荐系统等。
  • search 参数示例
search_params = {
    "metric_type": "L2",
    "params": {
        "nprobe": 10  # 搜索时访问的簇数量,值越大越精确但速度越慢
    }
}
1.3 HNSW(Hierarchical Navigable Small World)索引
  • 特点:基于图结构的索引,构建分层的小世界图。搜索时从图的高层开始,逐步向下层搜索,直到找到最接近的向量。
  • 优点
    • 在高维向量空间中搜索效率高,性能优于 IVF 索引。
    • 搜索结果精度较高,召回率损失相对较小。
    • 支持动态数据插入和删除,无需重新构建整个索引。
  • 缺点
    • 索引构建时间长,需要较多内存来存储图结构。
    • 随着数据量增加,索引维护成本升高。
  • 适用场景
    • 高维向量数据的搜索场景,如自然语言处理中的文本嵌入向量搜索。
    • 对搜索精度和效率都有较高要求,且数据动态变化频繁的场景。
  • search 参数示例
search_params = {
    "metric_type": "L2",
    "params": {
        "ef": 20  # 搜索时的动态访问列表大小,值越大越精确但速度越慢
    }
}
1.4 ANNOY(Approximate Nearest Neighbors Oh Yeah)索引
  • 特点:基于二叉树的近似最近邻搜索算法,构建多个二叉树,搜索时在多个二叉树中搜索并合并结果。
  • 优点
    • 索引构建速度快,占用内存相对较小。
    • 在低维向量空间中搜索效率较高。
  • 缺点
    • 搜索结果精度较低,召回率损失较大。
    • 不支持动态数据插入和删除,数据更新时需重新构建索引。
  • 适用场景
    • 低维向量数据的搜索场景,如地理位置数据搜索。
    • 对搜索效率要求高,但对精度要求相对较低的场景。
  • search 参数示例
search_params = {
    "metric_type": "L2",
    "params": {
        "search_k": 100  # 搜索时访问的节点数量,值越大越精确但速度越慢
    }
}

2. 构建索引的步骤

以下是使用 PyMilvus 构建不同索引类型的示例代码:

from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType

# 连接到 Milvus
connections.connect(alias="default", host='localhost', port='19530')

# 定义集合字段
fields = [
    FieldSchema(name="id", dtype=DataType.INT64, is_primary=True, auto_id=False),
    FieldSchema(name="vector", dtype=DataType.FLOAT_VECTOR, dim=128)
]

# 创建集合模式
schema = CollectionSchema(fields=fields, description="Example collection")

# 创建集合
collection = Collection(name="my_collection", schema=schema)

# 插入一些示例数据
import random
ids = [1, 2, 3]
vectors = [[random.random() for _ in range(128)] for _ in range(3)]
data = [ids, vectors]
collection.insert(data)
collection.flush()

# 构建 IVF 索引
ivf_index_params = {
    "metric_type": "L2",
    "index_type": "IVF_FLAT",
    "params": {"nlist": 128}
}
collection.create_index(field_name="vector", index_params=ivf_index_params)

# 构建 HNSW 索引
hnsw_index_params = {
    "metric_type": "L2",
    "index_type": "HNSW",
    "params": {"M": 16, "efConstruction": 50}
}
collection.create_index(field_name="vector", index_params=hnsw_index_params)

# 加载索引到内存
collection.load()

# 搜索示例
query_vector = [[random.random() for _ in range(128)]]
# 以 IVF 索引搜索为例
results = collection.search(
    data=query_vector,
    anns_field="vector",
    param=search_params,
    limit=10
)

# 断开连接
connections.disconnect("default")

3. 有索引跟没索引的区别

3.1 搜索效率
  • 无索引:进行全量向量遍历搜索,对集合中每个向量计算相似度。数据量增大时,搜索时间显著增长,效率极低。
  • 有索引:通过索引结构缩小搜索范围,避免全量遍历,提高搜索效率。如 IVF 索引只在部分簇内搜索,HNSW 索引利用图结构快速定位。
3.2 搜索精度
  • 无索引:全量遍历保证搜索结果精确,召回率 100%。
  • 有索引:多数为近似索引,存在一定召回率损失,但可通过调整参数平衡精度和效率。
3.3 数据更新和维护成本
  • 无索引:数据插入和删除简单,无需考虑索引更新维护,但数据量增加会使搜索性能下降。
  • 有索引:数据更新时需考虑索引更新维护,可能增加时间和空间开销。如 HNSW 索引支持动态更新但维护成本随数据量增加而升高,ANNOY 索引不支持动态更新,更新时需重建索引。