FAISS HNSW 是什么
IndexHNSWFlat 用多层邻近图组织向量,查询时从入口点沿图逐层逼近目标,靠 efSearch 控制搜索广度。索引跑在进程内,省掉网络往返与服务部署成本,适合离线批处理、单机检索服务和召回实验。索引用 write_index 保存、read_index 加载;保存的是索引结构本身,原始向量数据源要另行备份。
基本信息
| 构建参数 | M 控制每个节点的连边数,efConstruction 控制建图时的搜索广度 |
|---|---|
| 查询参数 | efSearch 越大召回越高、延迟越高 |
| 持久化 | faiss.write_index 写入文件,faiss.read_index 加载 |
| 版本敏感 | 索引文件与 faiss 版本强相关,升级前要验证可加载 |
典型使用场景
- 离线批量检索:把索引加载进脚本一口气跑完,不受服务并发限制
- 召回实验:对比 HNSW 与 IVF 在不同参数下的召回与耗时
- 单机小服务:向量规模在内存可容纳范围内,省去集群运维
- 索引快照归档:把某次构建的索引存下来,方便复现历史结果
- 迁移前的临时方案:正式向量库部署完成前先用进程内索引顶着
构建保存与加载
构建保存与加载
import faiss, numpy as np
d = 384
index = faiss.IndexHNSWFlat(d, 32) # 32 为 M,邻居数
index.hnsw.efConstruction = 200 # 建图搜索广度,越大越慢越准
xb = np.random.rand(200000, d).astype("float32")
index.add(xb) # 添加数据,注意先加全再保存
index.hnsw.efSearch = 64 # 查询期可随时调整
faiss.write_index(index, "kb_hnsw.faiss")
loaded = faiss.read_index("kb_hnsw.faiss")
print(loaded.ntotal) # 核对数量与预期一致
参数与影响
| 参数 | 作用 | 调大后的影响 |
|---|---|---|
| M | 每个节点的邻居连边数 | 召回更好,内存与建图时间上升 |
| efConstruction | 建图时的搜索广度 | 图质量更高,建索引更慢 |
| efSearch | 查询时的搜索广度 | 召回上升,延迟上升 |
| ntotal | 索引内向量总量 | 与预期不符说明写入不完整 |
索引文件与库版本强相关:升级 faiss 前先在测试环境验证可加载性,避免生产环境启动时才报错。
HNSW 不支持高效删除,删除后通常留空洞或需重建;需要频繁更新语料时,进程内索引的维护成本会比服务化向量库高,选型时要把更新频率一起考虑。