如何选择合适的索引类型
选择合适的Faiss索引并不简单,下面列出了一些关键问题,帮助你选择最适合的数据结构。本指南主要针对L2距离(欧氏距离)为主的应用场景。
- 每种索引结构都给出
index_factory字符串表示法。 - 如有参数,给出对应的
ParameterSpace参数。
页面底部提供了一个简明决策树。
你是否仅进行少量查询?
如果你计划仅进行少量查询(例如 1000~10000 次),那么索引建立的性能优势不会体现出来。直接计算会更加高效。
这个功能通过 "Flat" 索引实现。如果整个数据集无法一次性加载进内存(RAM),可以分批构建多个小索引,然后合并搜索结果。关于如何合并结果,请参考合并多个搜索结果。
你是否需要精确搜索结果?
如果需要:"Flat"
唯一能保证完全精确结果的索引是 IndexFlatL2 或 IndexFlatIP(IP 指点积即内积,常用于余弦相似度)。这两种索引为其他索引方法提供了对照基线。Flat 索引不对向量数据做压缩,也不会增加额外开销。
- 这种类型不支持带 ID 增加(
add_with_ids),只支持顺序添加。如果有必要使用add_with_ids,请选择"IDMap,Flat"。 - Flat 索引无需训练,也没有参数需要设置。
Supported on GPU: 支持
内存(RAM)是否是一个重要限制?
请注意,Faiss 所有索引都存放在内存中。以下讨论在不需要完全精确结果时,如果内存成为主要约束条件,如何在精度和速度之间做权衡。
如果内存不是限制:HNSW_M 或 IVF1024,PQ_Nx4fs,RFlat
- 如果有大量内存或数据集很小,HNSW(分层近邻小世界图,Hierarchical Navigable Small World)是最佳选择,速度快且精度高。参数 M 表示每个向量的链接数,推荐范围4到64,值越大精度越高但内存消耗也增加。速度和精度的权衡通过
efSearch设置。内存使用量约为 字节/向量(为向量维度)。 - HNSW 仅支持顺序插入,不支持
add_with_ids,如有需求需加前缀IDMap。无需训练,也不支持向量删除。 - 另一个选择是
IVF1024,PQ_Nx4fs,RFlat,较快但需两步检索:先用 IVF 粗搜索,再重排,涉及k_factor(重排行数)和nprobe(搜索的簇数量)两个参数。
Supported on GPU: 不支持
如果有限制,则选择 "...,Flat"
"..."表示数据集需要先聚类(后文会介绍)。- 聚类后,"Flat"只是将向量分桶存储,并未压缩数据,存储空间与原数据相当。
- 速度和精度权衡通过参数
nprobe控制。
Supported on GPU: 支持(聚类方法也须被GPU支持)
如果内存限制较大,选择 OPQ_M_D,...,PQ_Mx4fsr
- 若存储完整向量开销过大,可用OPQ(正交分组量化,Optimized Product Quantization)和PQ(产品量化,Product Quantization)组合。
- OPQ先将原始向量降维到 ,再用 PQ 将向量编码为 个4位码,总存储量为 字节/向量。
Supported on GPU: 支持
如果极度受限,选择 OPQ_M_D,...,PQ_M
- PQ 通常将向量压缩为 字节,通常 。如需更大编码长度可用 SQ(标量量化,Scalar Quantization)。
- OPQ 用于提前线性转换,便于更好压缩, 必须是 的整数倍,且 (最好),建议 。
- OPQ 只在 CPU 上完成,但性能影响极小。
Supported on GPU: 支持
数据集有多大?
数据规模会影响聚类方案(即上文 "..." 部分),数据将被划分为多个桶,检索时只访问少量桶(由nprobe控制)。聚类时建议用数据集的代表性样本进行训练。
若数据量低于 1 百万:...,IVF_K,...
K 推荐区间为 到 ,为向量数量。一般用k-means聚类。训练样本为 到 (越多越好)。
Supported on GPU: 支持
若数据量 1M ~ 10M :...,IVF65536_HNSW32,...
IVF 与 HNSW 结合,使用 HNSW 进行簇分配。训练样本为 到 。
Supported on GPU: 不支持(GPU请用上一种IVF方法)
若数据量 10M ~ 100M :...,IVF262144_HNSW32,...
同上,只是簇数提升为 262144()。训练会很慢,可以:
- 只在GPU上训练,其余在CPU,用train_ivf_with_gpu.ipynb.
- 两级聚类,详见demo_two_level_clustering.ipynb。
若数据量 1亿~10亿 :...,IVF1048576_HNSW32,...
同理,簇数为 1048576()。训练更慢!
- 在实际选择过程中,建议结合你的内存使用、检索精度、处理速度和数据量等需求进行综合权衡。
- 针对不同的数据集和场景,可以多次测试,选择最合适的索引结构。