HNSW 是什么
HNSW(Hierarchical Navigable Small World,分层可导航小世界图)把向量连成多层邻近图:上层稀疏、用于快速跳转到目标区域,底层稠密、用于精细搜索。查询从上层入口逐层下沉,只访问少量节点就能得到近似最近邻,是当前在线检索最常用的图索引之一,代价是索引与向量要常驻内存。
基本信息
| M | 每层连接数上限,常用 16 至 64;越大召回越高、内存越多 |
|---|---|
| efConstruction | 建索引时的候选队列长度,常用 100 至 500;越大越准、建索引越慢 |
| efSearch | 查询时的候选队列长度,可在检索时调整,越大越准越慢 |
| 内存占用 | 与向量条数、维度、M 成正比,需按总量预留 |
| 特性 | 近似检索,不保证返回精确最近邻 |
FAISS 构建与查询
FAISS 构建与查询
import faiss, numpy as np
d = 768
index = faiss.IndexHNSWFlat(d, 32) # M=32
index.hnsw.efConstruction = 200
index.hnsw.efSearch = 64
index.add(np.random.rand(10000, d).astype("float32"))
D, I = index.search(np.random.rand(1, d).astype("float32"), 10)Milvus 建索引
Milvus 建索引
# pymilvus 2.x
index_params = client.prepare_index_params()
index_params.add_index(field_name="vector", index_type="HNSW",
metric_type="COSINE", params={"M": 32, "efConstruction": 200})调参顺序
- 固定数据集与查询集,先取 M 为 16、efConstruction 为 200 作为基线
- 先只调 efSearch,观察召回率与延迟曲线,找到收益开始变缓的拐点
- 召回仍不达标再提高 M 与 efConstruction,并接受更长的建索引时间
- 上线前按目标并发压测,确认内存占用与 P95 延迟都在预算内
- 数据频繁删除时评估定期重建索引的成本,图结构不会自动修复
参数影响
| 参数 | 调大 | 调小 |
|---|---|---|
| M | 召回提升、内存与建索引时间上升 | 省内存,连通性不足时召回下降 |
| efConstruction | 索引质量更好、构建更慢 | 建得快,但图质量下降且难以事后补救 |
| efSearch | 查询更准、延迟上升 | 更快,可能漏掉正确的近邻 |
efSearch 可在查询时调整,适合按业务分级;M 与 efConstruction 影响内存与建索引时长,修改后必须重建索引才能生效。
适用与替代
- 十万到千万条、要求低延迟高召回时优先选它
- 内存紧张的大规模场景改看磁盘型索引或量化压缩方案
- 只做离线批处理时用精确索引即可,不必承担图索引的构建开销
- 数据量只有几万条时精确检索延迟已够用,图索引收益有限
- 需要频繁删除与重建时评估重建窗口,避免图连通性逐渐退化