当前位置: 首页 > news >正文

Milvus:索引概述(十二)

一、索引概述

1.1 索引基本概念

索引是构建在原始数据之上的附加数据结构,其设计完全依赖于底层的近似近邻搜索算法。核心作用是大幅降低向量检索的时间复杂度,让大规模数据查询从 “遍历全量数据” 变为 “精准定位候选集”,从而提升搜索效率。
但索引并非无成本,使用时需权衡以下代价:
  • 预处理时间:构建索引需要额外消耗计算资源和时间,数据量越大、索引类型越复杂,耗时越长。
  • 存储空间:索引本身需占用磁盘空间,量化类索引的空间开销较小,而原始向量索引(如 FLAT)开销与原始数据相当。
  • 内存占用:搜索过程中,索引的核心部分需加载到内存(RAM)中,否则会因频繁磁盘 IO 导致查询延迟飙升。
  • 召回率影响:近似索引会通过 “牺牲少量精度” 换取性能提升,这种损失通常在可接受范围内,但对精度敏感的场景需重点评估。

1.2 Milvus 索引特性

Milvus 的索引设计围绕 “灵活适配不同数据场景” 展开,核心特性如下:
  • 字段特异性:索引与数据字段一一绑定,例如为 FLOAT_VECTOR 类型字段构建 HNSW 索引,为 VARCHAR 类型字段构建反转索引,互不影响。
  • 类型多样性:针对向量、标量、JSON 等不同数据类型,提供专属优化的索引类型,避免 “一刀切” 的性能瓶颈。
  • 性能优化:聚焦向量搜索(核心场景)和标量过滤(辅助筛选)的协同优化,支持 “索引 + 过滤” 的高效查询组合。

二、数据类型与索引映射关系

2.1 向量数据类型索引

向量数据是 Milvus 的核心处理对象,不同向量类型的索引适配场景差异显著。

2.1.1 浮点向量

支持的向量类型包括 FLOAT_VECTOR(32 位浮点)、FLOAT16_VECTOR(16 位浮点)、bfloat16_vector(16 位脑浮点)、INT8_VECTOR(8 位整数量化向量),适用索引类型及场景如下:

索引类型

核心特点

适用场景

FLAT(平面索引)

无压缩、无近似,召回率 100%

小数据集(万级以内)、高精度需求

IVF_FLAT

聚类分桶 + 原始向量存储

中大规模数据集、平衡性能与精度

IVF_SQ8

聚类分桶 + 标量量化(8 位)

内存受限场景、追求高吞吐量

IVF_PQ

聚类分桶 + 乘积量化

超大规模数据集、内存资源紧张

IVF_RABITQ

增强型乘积量化,精度更优

内存受限且精度要求较高的场景

GPU_IVF_FLAT

基于 GPU 加速的 IVF_FLAT

大规模数据、高并发查询场景

GPU_IVF_PQ

基于 GPU 加速的 IVF_PQ

超大规模数据、GPU 资源充足

HNSW

分层图结构,低延迟

高维向量、低延迟查询需求

DISKANN

磁盘优化索引,内存占用极低

数据量超内存、稳定延迟需求

示例代码:为 FLOAT_VECTOR 字段构建 HNSW 索引

from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType# 1. 连接 Milvus 服务
connections.connect("default", host="localhost", port="19530")# 2. 定义集合结构(含 FLOAT_VECTOR 字段)
fields = [FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=128)  # 128维浮点向量
]
schema = CollectionSchema(fields, description="示例集合")
collection = Collection(name="float_vector_collection", schema=schema)# 3. 定义 HNSW 索引参数并创建
index_params = {"index_type": "HNSW","metric_type": "L2",  # 距离度量方式:L2(欧氏距离)、IP(内积)等"params": {"M": 16,  # 每个向量的邻居数量,范围4-64,越大索引精度越高、构建耗时越长"efConstruction": 200  # 构建时的候选集大小,范围100-500,越大构建质量越高}
}
collection.create_index(field_name="embedding", index_params=index_params)
2.1.2 二进制向量
二进制向量(元素仅为 0 或 1)的存储和计算成本更低,适用索引类型为 BIN_FLAT 和 BIN_IVF_FLAT
  • BIN_FLAT:无近似的二进制向量索引,召回率 100%,适用于小规模二进制向量数据集。
  • BIN_IVF_FLAT:聚类分桶的二进制向量索引,适用于大规模二进制向量场景,查询速度远快于 BIN_FLAT
示例代码:为二进制向量字段构建 BIN_IVF_FLAT 索引
# 定义二进制向量字段(dim 为向量维度)
fields = [FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),FieldSchema(name="bin_embedding", dtype=DataType.BINARY_VECTOR, dim=256)
]
schema = CollectionSchema(fields, description="二进制向量集合")
collection = Collection(name="binary_vector_collection", schema=schema)# 定义 BIN_IVF_FLAT 索引参数
index_params = {"index_type": "BIN_IVF_FLAT","params": {"nlist": 1024  # 聚类分桶数量,建议为数据集大小的开平方(如100万数据设为1024)}
}
collection.create_index(field_name="bin_embedding", index_params=index_params)
2.1.3 稀疏浮点向量
稀疏浮点向量(大部分元素为 0,仅少量非零元素)适用于文本检索等场景,支持的索引类型:
  • MINHASH_LSH:基于局部敏感哈希的索引,适用于稀疏向量的快速去重和相似性搜索。
  • 稀疏反转索引:通过记录非零元素的位置和值构建索引,大幅减少无效计算,提升查询效率。

2.2 标量数据类型索引

标量数据(如字符串、数值、布尔值)通常用于 “过滤条件”(如 where id > 1000),Milvus 为不同标量类型提供专属索引优化。
2.2.1 字符串类型(VARCHAR)
  • 推荐索引:反转索引(默认推荐),支持模糊查询(如 like '%keyword%')、前缀查询(如 like 'prefix%'),查询效率高。
  • 其他选项:BITMAP(适用于低基数字符串,如性别、类别标签)、Trie(适用于前缀匹配场景,如字典查询)。
示例代码:为 VARCHAR 字段构建反转索引
fields = [FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),FieldSchema(name="product_name", dtype=DataType.VARCHAR, max_length=100)  # 字符串字段
]
schema = CollectionSchema(fields, description="商品集合")
collection = Collection(name="product_collection", schema=schema)# 定义反转索引参数(字符串字段默认索引类型为反转索引)
index_params = {"index_type": "INVERTED","params": {}
}
collection.create_index(field_name="product_name", index_params=index_params)# 示例查询:筛选商品名称包含"手机"的记录
collection.load()
query_expr = "product_name like '%手机%'"
results = collection.query(expr=query_expr, output_fields=["id", "product_name"])
2.2.2 布尔类型(BOOL)
  • 推荐索引:BITMAP(默认),适用于高并发的布尔过滤(如 where is_active = True),查询速度极快。
  • 其他选项:反转索引,适用于布尔字段与其他标量字段的联合过滤场景。
2.2.3 数值类型
支持的数值类型包括 INT8/INT16/INT32/INT64(整数)、FLOAT/DOUBLE(浮点数),适用索引:
  • 反转索引:支持范围查询(如 price between 100 and 200)、等值查询(如 category_id = 5),适配所有数值类型。
  • STL_SORT:仅限整数类型,基于排序的索引,范围查询效率优于反转索引,但插入更新性能较差。
示例代码:为 INT64 字段构建 STL_SORT 索引
fields = [FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),FieldSchema(name="category_id", dtype=DataType.INT64)  # 整数类型字段
]
schema = CollectionSchema(fields, description="分类集合")
collection = Collection(name="category_collection", schema=schema)# 定义 STL_SORT 索引参数(仅支持整数类型)
index_params = {"index_type": "STL_SORT","params": {}
}
collection.create_index(field_name="category_id", index_params=index_params)# 示例查询:筛选 category_id 在 1-10 之间的记录
collection.load()
query_expr = "category_id in [1,2,3,4,5,6,7,8,9,10]"
results = collection.query(expr=query_expr, output_fields=["id", "category_id"])
2.2.4 数组类型
数组元素支持 BOOLINT8/16/32/64FLOAT/DOUBLEVARCHAR,索引选择规则:
  • 推荐索引:BITMAP(适用于低基数数组元素,如标签数组 ["tag1", "tag2"])。
  • 适用索引:反转索引(适用于高基数数组元素,如数值数组 [100, 200, 300])。
2.2.5 JSON 类型
JSON 字段支持嵌套结构(如 {"user": {"age": 25, "city": "Beijing"}}),仅支持反转索引,可通过 json_extract 函数进行过滤查询。
示例代码:为 JSON 字段构建反转索引并查询
fields = [FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),FieldSchema(name="user_info", dtype=DataType.JSON)  # JSON 字段
]
schema = CollectionSchema(fields, description="用户集合")
collection = Collection(name="user_collection", schema=schema)# 为 JSON 字段构建反转索引
index_params = {"index_type": "INVERTED","params": {}
}
collection.create_index(field_name="user_info", index_params=index_params)# 示例查询:筛选年龄大于 25 且城市为 Beijing 的用户
collection.load()
query_expr = 'json_extract(user_info, "$.user.age") > 25 and json_extract(user_info, "$.user.city") == "Beijing"'
results = collection.query(expr=query_expr, output_fields=["id", "user_info"])

三、向量索引架构解析

3.1 索引核心组件

Milvus 向量索引的架构采用 “模块化设计”,由三个核心部分组成,支持灵活组合以适配不同场景:

组件

必要性

核心作用

示例

数据结构

必需

定义向量的组织方式,决定搜索效率

IVF 的 “聚类分桶”、HNSW 的 “分层图”

量化

可选

压缩向量数据,降低内存 / 存储开销

SQ8 的标量量化、PQ 的乘积量化

精炼器

可选

修正量化误差,提升召回率

FP32 精炼器(用原始精度重算距离)

3.2 索引工作流程

Milvus 向量索引的工作流程分为 “创建阶段” 和 “查询阶段”,全程围绕 “高效筛选候选集 + 精准计算结果” 展开:
3.2.1 创建阶段
  1. 根据选定的索引类型,初始化对应的数据结构(如 IVF 的聚类分桶、HNSW 的分层图)。
  2. 若启用量化(如 IVF_PQ、HNSW-PQ),则训练量化模型(如 PQ 的编码本),并将原始向量压缩为量化后的数据。
  3. 确定最佳扩展率(expansion rate),即候选集规模为 topK × expansion rate,用于平衡查询速度和召回率(默认值通常为 5,可手动调整)。
3.2.2 查询阶段
  1. 客户端发送查询请求(含查询向量、topK、过滤条件等参数)。
  2. Milvus 加载索引核心数据到内存,根据数据结构快速检索 topK × expansion rate 个候选向量(如 IVF 扫描邻近桶、HNSW 遍历分层图)。
  3. 若启用精炼器,对候选向量使用更高精度重新计算距离(如 FP32 精度),筛选出最精准的 topK 结果。
  4. 将最终结果返回给客户端。
流程示意图

四、索引数据结构详解

4.1 倒排文件(IVF)系列

IVF(Inverted File)是 Milvus 中最常用的索引数据结构之一,核心思想是 “聚类分桶”,大幅减少查询时的向量比对次数。
4.1.1 工作原理
  1. 聚类分桶:构建索引时,使用 k-means 算法将所有向量聚类为 nlist 个桶(簇),每个桶有一个中心点向量。
  2. 索引存储:记录每个向量所属的桶 ID,以及桶内向量的存储位置(原始向量或量化向量)。
  3. 查询过程:
  • 计算查询向量与所有桶中心点的距离,筛选出距离最近的 nprobe 个桶(nprobe 为查询参数,默认 10)。
  • 仅遍历这 nprobe 个桶内的向量,计算与查询向量的距离。
  • 排序后返回 topK 结果。
4.1.2 核心参数说明

参数名

作用

调整建议

nlist

聚类分桶数量

建议为数据集大小的开平方(如 100 万数据设为 1024)

nprobe

查询时扫描的桶数量

越大召回率越高、速度越慢(默认 10,范围 1-nlist)

4.1.3 适用场景
  • 大规模数据集(百万级及以上),需要高吞吐量查询。
  • 计算成本敏感的应用场景(如 CPU 资源有限)。
  • 大 topK 搜索(topK > 2000),性能优于基于图的索引。
示例代码:IVF_PQ 索引构建与查询
# 1. 构建 IVF_PQ 索引
index_params = {"index_type": "IVF_PQ","metric_type": "IP","params": {"nlist": 2048,  # 分桶数量"m": 8,  # PQ 子向量数量(需整除向量维度,如128维设为8则每个子向量16维)"nbits": 8,  # 每个子向量的编码位数(通常为8,压缩率=32/nbits)"nprobe": 32  # 查询时扫描的桶数量(默认10,此处调高以提升召回率)}
}
collection.create_index(field_name="embedding", index_params=index_params)# 2. 加载集合并查询
collection.load()
query_vectors = [[0.1, 0.2, ..., 0.128]]  # 128维查询向量
search_params = {"params": {"nprobe": 32}  # 查询时的 nprobe 可覆盖索引构建时的参数
}
results = collection.search(data=query_vectors,anns_field="embedding",param=search_params,limit=10,  # topK=10output_fields=["id"]
)

4.2 基于图的结构(HNSW)

HNSW(Hierarchical Navigable Small World)是一种基于分层图的索引结构,核心优势是 “低延迟”,尤其适用于高维向量场景。
4.2.1 工作原理
  1. 分层图构建:
  • 为每个向量构建多层邻居关系,上层为稀疏图(用于快速导航),下层为稠密图(用于精准筛选)。
  • 构建时随机为每个向量分配一个层级,高层向量可覆盖更大范围的导航,低层向量聚焦局部精准匹配。
  1. 查询过程:
  • 从最高层的一个随机节点开始,遍历其邻居节点,找到距离查询向量最近的节点,作为下一层的起始节点。
  • 逐层向下遍历,直到最底层,最终筛选出距离最近的 topK 向量。
  • 搜索复杂度为 O (log n),远低于 IVF 的 O (n/k)。
4.2.2 核心参数说明

参数名

作用

调整建议

M

每个向量的邻居数量

范围 4-64,越大精度越高、构建耗时越长(默认 16)

efConstruction

构建时的候选集大小

范围 100-500,越大构建质量越高(默认 200)

ef

查询时的候选集大小

范围 10-1000,越大召回率越高、速度越慢(默认 100)

4.2.3 适用场景
  • 高维向量空间(如 512 维、1024 维向量),IVF 性能下降明显时。
  • 低延迟查询需求(如实时推荐、在线检索,要求响应时间毫秒级)。
  • 小 topK 搜索(topK < 2000),召回率和速度表现最优。
示例代码:HNSW 索引构建与查询优化
# 1. 构建 HNSW 索引(高维向量场景,如256维)
index_params = {"index_type": "HNSW","metric_type": "L2","params": {"M": 32,  # 邻居数量增加,提升精度"efConstruction": 400  # 构建候选集增大,提升索引质量}
}
collection.create_index(field_name="embedding", index_params=index_params)# 2. 低延迟查询配置(ef 设为 50,平衡速度和精度)
collection.load()
query_vectors = [[0.05, 0.1, ..., 0.256]]  # 256维查询向量
search_params = {"params": {"ef": 50}  # ef 越小,查询速度越快
}
results = collection.search(data=query_vectors,anns_field="embedding",param=search_params,limit=20,  # topK=20output_fields=["id"]
)
4.3 两种结构对比

特性

IVF 系列

基于图的结构(HNSW)

数据结构

聚类分桶

分层导航图

搜索复杂度

O (n/k)(k 为 nlist)

O(log n)

内存占用

较低(支持量化压缩)

较高(原始向量或轻量量化)

构建时间

中等(聚类过程耗时)

较长(分层图构建复杂)

适用场景

大规模数据集、高吞吐量、大 topK

高维空间、低延迟、小 topK

召回率调整

通过 nprobe 调整(灵活)

通过 ef 调整(灵活)

五、量化技术

量化技术的核心目的是 “压缩向量数据”,降低内存和存储开销,同时尽可能减少精度损失。Milvus 支持两种主流量化方式:标量量化(SQ8)和乘积量化(PQ)。

5.1 标量量化(SQ8)

5.1.1 工作原理
将每个向量的每个维度(32 位浮点)压缩为 8 位整数(1 字节),压缩率固定为 4:1。
  • 压缩过程:计算所有向量在每个维度上的最大值和最小值,将该维度的浮点值映射到 0-255 的整数区间。
  • 解压过程:查询时将 8 位整数反向映射回浮点值,再计算距离。
5.1.2 核心特点
  • 内存节省:相比原始 32 位浮点向量,减少 75% 内存使用(如 128 维向量从 512 字节压缩到 128 字节)。
  • 精度损失:较小,适合对精度要求适中、内存受限的场景。
  • 计算成本:低,压缩和解压过程简单,CPU 开销小。
5.1.3 适用场景
  • 平衡型应用,既要控制内存开销,又不想大幅牺牲召回率。
  • 中等规模数据集(百万级),CPU 资源有限。

5.2 乘积量化(PQ)

5.2.1 工作原理
  1. 向量分割:将原始向量分割为 m 个互不重叠的子向量(如 128 维向量分割为 8 个 16 维子向量)。
  2. 聚类编码:对每个子向量使用 k-means 算法聚类为 2^nbits 个簇,每个簇分配一个编码(码字)。
  3. 压缩存储:每个子向量用 nbits 位编码表示,整个向量的编码长度为 m×nbits 位。
5.2.2 核心参数说明

参数名

作用

调整建议

m

子向量数量

需整除向量维度(如 128 维设为 8、16)

nbits

每个子向量的编码位数

通常为 8(256 个簇),支持 4-16

5.2.3 核心特点
  • 压缩率:灵活可调,4:1 到 32:1(如 m=8、nbits=8 时压缩率为 4:1;m=16、nbits=4 时压缩率为 8:1)。
  • 内存节省:75% - 97%,压缩率远高于 SQ8。
  • 精度损失:中等,压缩率越高,精度损失越大。
  • 计算成本:中等,子向量聚类和编码过程比 SQ8 复杂。
5.2.4 适用场景
  • 内存敏感环境(如内存不足以存储原始向量或 SQ8 压缩向量)。
  • 超大规模数据集(千万级及以上),需控制索引内存开销。

5.3 两种量化技术对比

指标

标量量化(SQ8)

乘积量化(PQ)

压缩率

固定 4:1

4:1 到 32:1(可调)

内存节省

75%

75% - 97%

精度损失

较小

中等

计算成本

中等

适用场景

平衡型应用

内存敏感环境

示例代码:量化索引性能对比测试

import time
import numpy as np# 生成测试数据(100万条128维向量)
n_data = 1000000
dim = 128
vectors = np.random.randn(n_data, dim).astype(np.float32)
ids = np.arange(n_data).astype(np.int64)# 定义集合(省略字段和 schema 定义,同前)
collection = Collection(name="quantization_test", schema=schema)# 插入数据
collection.insert([ids, vectors])# 1. 构建 IVF_SQ8 索引并测试
sq8_index_params = {"index_type": "IVF_SQ8","metric_type": "L2","params": {"nlist": 1024}
}
collection.create_index("embedding", sq8_index_params)
collection.load()# 测试查询速度
query_vectors = np.random.randn(10, dim).astype(np.float32)  # 10个查询向量
start_time = time.time()
sq8_results = collection.search(data=query_vectors, anns_field="embedding", param={"params": {"nprobe": 20}}, limit=10)
sq8_time = time.time() - start_time
print(f"IVF_SQ8 查询耗时:{sq8_time:.4f}s")# 2. 构建 IVF_PQ 索引并测试
collection.drop_index("embedding")  # 删除原有索引
pq_index_params = {"index_type": "IVF_PQ","metric_type": "L2","params": {"nlist": 1024, "m": 8, "nbits": 8}
}
collection.create_index("embedding", pq_index_params)start_time = time.time()
pq_results = collection.search(data=query_vectors, anns_field="embedding", param={"params": {"nprobe": 20}}, limit=10)
pq_time = time.time() - start_time
print(f"IVF_PQ 查询耗时:{pq_time:.4f}s")# 对比召回率(以 FLAT 索引为基准)
collection.drop_index("embedding")
flat_index_params = {"index_type": "FLAT", "metric_type": "L2"}
collection.create_index("embedding", flat_index_params)
flat_results = collection.search(data=query_vectors, anns_field="embedding", param={}, limit=10)# 计算召回率(简化计算:交集数量/FLAT结果数量)
def calculate_recall(approx_results, flat_results):recall_sum = 0.0for approx_res, flat_res in zip(approx_results, flat_results):approx_ids = set([hit.id for hit in approx_res])flat_ids = set([hit.id for hit in flat_res])intersection = approx_ids & flat_idsrecall_sum += len(intersection) / len(flat_ids)return recall_sum / len(query_vectors)sq8_recall = calculate_recall(sq8_results, flat_results)
pq_recall = calculate_recall(pq_results, flat_results)
print(f"IVF_SQ8 召回率:{sq8_recall:.4f}")
print(f"IVF_PQ 召回率:{pq_recall:.4f}")

六、精炼器机制

6.1 作用原理

量化技术(如 SQ8、PQ)本质是 “有损压缩”,会导致向量距离计算存在误差,进而影响召回率。精炼器的核心作用是 “修正误差”:
  • 量化索引检索出 topK × expansion rate 个候选向量后,精炼器对这些候选向量使用更高精度(如 FP32)重新计算距离。
  • 过滤掉因量化误差导致的 “伪近邻” 向量,保留真正距离最近的 topK 结果,从而提升召回率。

6.2 常用精炼器:FP32 精炼器

FP32 精炼器是 Milvus 中最常用的精炼器,工作流程:
  1. 索引检索阶段:量化索引返回 topK × expansion rate 个候选向量(量化形式或原始形式)。
  2. 精炼阶段:加载候选向量的原始 FP32 精度数据,重新计算与查询向量的距离。
  3. 结果筛选:根据重新计算的距离排序,返回 topK 结果。

6.3 适用场景

  • 搜索效率和精度需要权衡的应用(如既想使用量化索引节省内存,又不想牺牲过多召回率)。
  • 语义搜索、推荐系统等对结果质量敏感的场景(召回率直接影响用户体验)。
示例代码:启用 FP32 精炼器
# 构建 IVF_PQ 索引并启用 FP32 精炼器
index_params = {"index_type": "IVF_PQ","metric_type": "IP","params": {"nlist": 2048,"m": 8,"nbits": 8,"refiner_type": "FP32",  # 启用 FP32 精炼器"expansion_rate": 10  # 候选集规模 = topK × 10(默认5,调高提升召回率)}
}
collection.create_index(field_name="embedding", index_params=index_params)# 查询时自动触发精炼器
collection.load()
results = collection.search(data=query_vectors,anns_field="embedding",param={"params": {"nprobe": 32}},limit=10
)

七、性能权衡分析

7.1 关键性能指标

7.1.1 构建时间
  • 定义:从索引创建请求发起,到索引构建完成的总时间。
  • 影响因素:数据量、索引类型、量化参数、硬件性能(CPU/GPU)。
  • 对比:FLAT 索引构建时间最短(仅需存储原始向量);HNSW 索引构建时间最长(分层图构建复杂);IVF 系列居中(聚类分桶耗时)。
7.1.2 QPS(每秒查询次数)
  • 定义:单位时间内可处理的查询请求数量,反映系统吞吐量。
  • 对比:
    • 基于图的索引(HNSW):小 topK 场景下 QPS 通常优于 IVF 变体。
    • IVF 变体:大 topK 场景(topK > 2000)下 QPS 更高(聚类分桶可减少无效计算)。
    • GPU 加速索引(GPU_IVF_FLAT):QPS 远高于 CPU 版本,适合高并发场景。
7.1.3 召回率
  • 定义:查询结果中真正相关的向量占所有相关向量的比例,反映结果准确性。
  • 对比:
    • FLAT 索引:召回率 100%(无近似)。
    • PQ vs SQ8:相同压缩率下,PQ 召回率通常更高,但计算成本略高。
    • 精炼器:启用后可提升召回率 5%-15%,但会增加少量查询延迟。

7.2 容量考虑

7.2.1 内存适配策略
  • 1/4 数据适合内存:考虑使用 DiskANN 索引,数据主要存储在磁盘 / SSD,内存仅加载索引元数据,延迟稳定。
  • 全部数据适合内存:优先选择基于内存的索引(HNSW、IVF_FLAT),搭配 mmap 技术(内存映射文件),平衡内存使用和查询速度。
  • 内存极度受限:使用 IVF_PQ 索引,通过高压缩率换取最大容量,必要时启用精炼器补偿精度。
7.2.2 磁盘使用
  • DiskANN 优势:当大部分数据无法装入内存时,DiskANN 通过磁盘优化的索引结构,提供比 mmap 更稳定的查询延迟。
  • mmap 限制:mmap 依赖操作系统的页面缓存,当数据量超过内存时,会频繁触发页面置换,导致延迟波动。

八、召回率优化策略

8.1 过滤率与索引选择

过滤率(Filter Rate)是指查询中符合过滤条件的向量占总向量的比例,直接影响索引性能,推荐匹配关系如下:

过滤率范围

推荐索引类型

说明

< 85%

基于图的索引(HNSW)

过滤后有效数据量少,低延迟优势明显

85% - 95%

IVF 变体(IVF_FLAT)

平衡性能与召回率,性价比最高

> 98%

蛮力(FLAT)

过滤后数据量接近全量,索引优势不明显,直接遍历更高效

注意:上述建议为经验值,实际需通过基准测试验证(如不同过滤率下的 QPS 和召回率对比)。

8.2 搜索性能与 Top-K

8.2.1 小 Top-K 搜索(topK ≤ 2000)
  • 需求:高召回率、低延迟。
  • 推荐:HNSW 索引,其分层图结构可快速定位近邻向量,性能优于 IVF 系列。
  • 优化:适当调高 ef 参数(如 100→200),提升召回率。
8.2.2 大 Top-K 搜索(topK > 2000)
  • 需求:高吞吐量、稳定性能。
  • 推荐:IVF 变体(IVF_FLAT、IVF_SQ8),聚类分桶可减少需遍历的向量数量,避免 HNSW 大 topK 场景下的性能下降。
  • 优化:调高 nprobe 参数(如 10→50),确保召回率。
8.2.3 中等 Top-K + 高过滤率
  • 需求:平衡召回率、延迟、吞吐量。
  • 推荐:IVF 变体,高过滤率下有效数据量减少,IVF 的聚类分桶优势依然存在,且构建成本低于 HNSW。

九、决策矩阵:索引类型选择指南

场景描述

推荐索引类型

核心优化点

原始数据适合内存,低延迟 / 高召回率

HNSW + 可选精炼器

分层图结构实现低延迟,精炼器提升精度

数据存储在磁盘 / SSD,延迟敏感

DiskANN

磁盘优化索引,延迟稳定

磁盘数据,有限 RAM

IVF_PQ/SQ8 + 高过滤率(>95%)

量化压缩节省内存,高过滤率提升效率

极高召回率(>99%)

FLAT + 可选 GPU

无近似保证精度,GPU 加速提升速度

大 topK(≥数据集的 1%)

IVF 系列(IVF_FLAT)

簇剪枝减少计算量,提升吞吐量

十、内存使用估算

10.1 IVF 索引内存使用计算

以 100 万个 128 维 FLOAT_VECTOR 为例,内存占用由三部分组成:中心点内存、簇分配内存、量化压缩内存。
10.1.1 基础计算
  • 中心点内存:nlist × dim × 4 bytes(4 bytes 为 float 类型占用空间)。示例:2000 个簇 × 128 维 × 4 bytes = 1.0 MB。
  • 簇分配内存:n_data × 2 bytes(每个向量用 2 bytes 存储簇 ID)。示例:100 万向量 × 2 bytes = 2.0 MB。
  • 量化压缩内存:
    • PQ(8 个子量化器):n_data × m bytes(m 为子向量数量,每个子向量编码占 1 byte)。示例:100 万向量 × 8 bytes = 8.0 MB。
    • SQ8:n_data × dim × 1 byte(每个维度压缩为 1 byte)。示例:100 万向量 × 128 维 × 1 byte = 128 MB。
    • IVF_FLAT(无量化):n_data × dim × 4 bytes(原始向量存储)。示例:100 万向量 × 128 维 × 4 bytes = 512 MB。
10.1.2 不同配置内存估算

配置

各部分内存占用

总内存

IVF-PQ(无精炼)

1.0 MB + 2.0 MB + 8.0 MB

11.0 MB

IVF-PQ + 10% 精炼

1.0 MB + 2.0 MB + 8.0 MB + 51.2 MB

62.2 MB

IVF-SQ8(无精炼)

1.0 MB + 2.0 MB + 128 MB

131.0 MB

IVF-FLAT(全原始)

1.0 MB + 2.0 MB + 512 MB

515.0 MB

10.1.3 精炼开销计算
精炼器仅占用少量内存(处理候选集时),公式:topK × expansion rate × dim × 4 bytes。示例:topK=10,expansion rate=5 → 50 个候选向量 × 128 维 × 4 bytes = 25.6 KB。

10.2 基于图的索引内存使用

以 100 万个 128 维 FLOAT_VECTOR 为例,HNSW 索引内存由图结构内存和向量内存组成。
10.2.1 基础计算
  • 图结构内存:n_data × M × 4 bytes(M 为每个向量的邻居数量,4 bytes 存储邻居 ID)。示例:100 万向量 × 32 个邻居 × 4 bytes = 128 MB。
  • 原始向量内存:n_data × dim × 4 bytes。示例:100 万向量 × 128 维 × 4 bytes = 512 MB。
  • 总内存:128 MB + 512 MB = 640 MB。
10.2.2 量化压缩效果(HNSW-PQ)
  • PQ 压缩内存:n_data × m bytes(m=8 个子量化器)。示例:100 万向量 × 8 bytes = 8 MB。
  • HNSW-PQ 总内存:128 MB + 8 MB = 136 MB(压缩率约 64 倍)。
10.2.3 精炼开销
与 IVF 索引相同,约 25.6 KB(topK=10、expansion rate=5 时)。

十一、总结与最佳实践

11.1 索引选择核心原则

  1. 明确需求:优先确定核心指标(如召回率≥95%、延迟≤100ms),再选择索引类型。
  2. 数据规模:小规模(万级)选 FLAT,中大规模(百万级)选 IVF 系列,超大规模(千万级)选 IVF_PQ/DiskANN。
  3. 查询模式:小 topK 低延迟选 HNSW,大 topK 高吞吐量选 IVF,高过滤率选 IVF 或 FLAT。
  4. 实验验证:通过基准测试(如测试不同索引的构建时间、QPS、召回率),确定最优配置。

11.2 性能优化建议

  1. 内存优化:合理使用量化(SQ8/PQ)和 mmap 技术,避免内存溢出。
  2. 磁盘利用:超大规模数据优先考虑 DiskANN,避免 mmap 导致的延迟波动。
  3. 精度平衡:量化索引搭配精炼器,在内存开销和召回率间找到平衡点。
  4. 硬件利用:GPU 资源充足时,使用 GPU 加速索引(GPU_IVF_FLAT),大幅提升吞吐量。

http://www.dtcms.com/a/569970.html

相关文章:

  • 【25真题】C9之一,质量极高!
  • GitPuk零基础学习,如何进行标签管理
  • Git多分支开发规范与操作指南
  • 国外网站app网址提交大全
  • pulsar SDK在Linux的使用
  • 11.4八股
  • Trae-Agent 使用本地模型
  • 哪个网站开发小程序网站建设与维护的软件
  • Docker(四)_导出容器(不含历史层)
  • GitHub Copilot CLI: How to get started
  • Android ANR的解决方案
  • 亚马逊云科技与OpenAI战略合作深度分析:算力联盟重塑AI产业格局
  • 个人接外包的网站心悦俱乐部官方网站怎么做任务
  • 【Ros2学习】话题的发布与请求
  • 肥猫网站建设广西省河池建设局网站
  • CentOS7安装docker教程
  • 论文网站建设与运营拖曳式网站建设
  • Jenkins持续集成入门指南:自动化构建与部署的最佳实践
  • 山西省建设信息网站汇点远程app下载安装
  • 阿里云手机网站建设打电话拉客户用网站做广告怎么做 好做吗
  • hexo做网站wordpress内容分页在哪改
  • 游戏网站后台建设美橙云建站
  • 数据备份策略:全量 / 增量 / 差异备份、备份周期规划
  • LeetCode 322. 零钱兑换
  • Redis黑马点评 Feed流
  • 域名后缀cn做网站河北手机网站建设
  • U-Net保姆级教程:从原理到医学细胞分割实战(PyTorch版)!
  • mini-bitcask学习笔记
  • 东莞网站建设公司哪家好电商平面设计主要做什么
  • 解决远程调用微服务之后无法通过上下文获取用户id问题