
🧠 记忆锚点:Flat 做真值,HNSW 用图换低延迟,IVF 先分桶,PQ 用精度换内存;用同一数据集压测选型。
💡 完整答案
主流索引类型对比:
| 索引类型 | 全称 | 原理 | 速度 | 精度 | 内存 | 适用场景 |
|---|---|---|---|---|---|---|
| HNSW | Hierarchical Navigable Small World | 多层图结构,贪心搜索 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | 高 | 追求速度,内存充足 |
| IVF | Inverted File Index | 先聚类,再在簇内搜索 | ⭐⭐⭐ | ⭐⭐⭐⭐ | 中 | 数据量大,可接受精度损失 |
| IVF-PQ | IVF + Product Quantization | IVF + 向量压缩 | ⭐⭐⭐⭐ | ⭐⭐⭐ | 低 | 内存受限,大数据量 |
| LSH | Locality Sensitive Hashing | 局部敏感哈希 | ⭐⭐⭐⭐ | ⭐⭐ | 低 | 超大规模,近似即可 |
| Flat | 暴力搜索 | 计算所有距离 | ⭐ | ⭐⭐⭐⭐⭐ | 中 | <1 万条数据 |
一、HNSW(层次导航小世界)
原理:
HNSW = 多层图结构 + 贪心搜索
1. 构建多层图:
- 顶层:节点少,长距离跳跃
- 底层:节点多,精细搜索
- 每层都是一个小世界网络
2. 搜索过程:
- 从顶层入口开始
- 贪心搜索:找最近的邻居
- 找到局部最优后,下降到下一层
- 重复直到最底层图示:
Layer 2 (顶层): A ───── B
│
Layer 1 (中层): C ───── D ───── E
│
Layer 0 (底层): F ───── G ───── H ───── I优点:
- ✅ 在合适参数和数据分布下通常有很好的低延迟表现
- ✅ 精度最高(接近暴力搜索)
- ✅ 支持实时插入
缺点:
- ❌ 内存占用高(存储图结构)
- ❌ 构建时间长
性能数据:
- 100 万条数据,检索延迟:< 10ms
- 内存占用:约 1-2GB(1536 维)
- 召回率(Recall@10):> 95%
适用场景:
- 数据量 < 1000 万
- 内存充足
- 追求低延迟
代码示例(Milvus):
python
index_params = {
"metric_type": "IP", # 内积相似度
"index_type": "HNSW",
"params": {
"M": 16, # 每个节点的最大连接数
"efConstruction": 200 # 构建时的搜索范围
}
}
collection.create_index(field_name="embedding", index_params=index_params)二、IVF(倒排文件索引)
原理:
IVF = 聚类 + 分桶搜索
1. 训练阶段:
- 用 K-Means 把向量聚成 N 个簇(如 1024 个)
- 每个簇有一个质心(centroid)
2. 索引阶段:
- 每个向量分配到最近的簇
- 建立 簇 ID → 向量列表 的倒排索引
3. 搜索阶段:
- 计算查询向量与各簇质心的距离
- 选最近的 k 个簇(如 k=10)
- 只在这 k 个簇内暴力搜索图示:
查询向量 Q
↓
┌───────┼───────┐
↓ ↓ ↓
簇 1 簇 2 簇 3 ← 计算与质心距离
│ │ │
└───────┼───────┘
↓
选最近的 3 个簇
↓
只在选中簇内暴力搜索优点:
- ✅ 内存占用适中
- ✅ 适合大数据量
- ✅ 构建速度快
缺点:
- ❌ 精度有损失(近似搜索)
- ❌ 需要调参(簇数量)
性能数据:
- 100 万条数据,检索延迟:~50-100ms
- 内存占用:约 500MB-1GB
- 召回率(Recall@10):85-90%
适用场景:
- 数据量 100 万 -1 亿
- 可接受精度损失
- 离线批量构建
代码示例(FAISS):
python
import faiss
# 创建 IVF 索引
d = 1536 # 向量维度
quantizer = faiss.IndexFlatL2(d) # 质心索引
index = faiss.IndexIVFFlat(quantizer, d, nlist=1024) # 1024 个簇
# 训练
index.train(vectors)
# 添加
index.add(vectors)
# 搜索
index.nprobe = 10 # 搜索 10 个簇
D, I = index.search(query_vector, k=10)三、IVF-PQ(乘积量化)
原理:
IVF-PQ = IVF 聚类 + 向量压缩
1. IVF 聚类(同上)
2. 乘积量化(PQ):
- 把 1536 维向量切成 M 段(如 16 段)
- 每段 96 维(1536/16)
- 每段独立聚类(如 256 个质心)
- 用质心 ID(1 字节)代替原始向量
- 1536 维 float(6144 字节)→ 16 字节
3. 搜索:
- 在压缩空间计算近似距离
- 速度快,内存小压缩效果:
原始向量:1536 维 × 4 字节 (float32) = 6144 字节
PQ 压缩后:16 段 × 1 字节 (uint8) = 16 字节
压缩率:6144 / 16 = 384 倍优点:
- ✅ 内存占用极低
- ✅ 适合超大数据量
- ✅ 检索速度快
缺点:
- ❌ 精度损失较大
- ❌ 需要调参(分段数)
性能数据:
- 1000 万条数据,内存占用:约 1-2GB
- 检索延迟:~20-50ms
- 召回率(Recall@10):80-85%
适用场景:
- 数据量 > 1000 万
- 内存受限
- 可接受精度损失
四、LSH(局部敏感哈希)
原理:
LSH = 哈希 + 桶内搜索
1. 核心思想:
- 相似的向量哈希后落在同一个桶
- 不相似的向量哈希后落在不同桶
2. 哈希函数:
- h(v) = sign(w · v) w 是随机向量
- 多个哈希函数组成哈希表
3. 搜索:
- 计算查询向量的哈希值
- 找到对应桶
- 只在这个桶内暴力搜索优点:
- ✅ 内存占用低
- ✅ 适合超大规模
- ✅ 理论保证
缺点:
- ❌ 精度最低
- ❌ 哈希函数设计复杂
适用场景:
- 数据量 > 1 亿
- 精度要求不高
- 近似搜索即可
五、Flat(暴力搜索)
原理:
计算查询向量与所有向量的距离,排序取 top-k优点:
- ✅ 精度 100%
- ✅ 无需构建索引
- ✅ 实现简单
缺点:
- ❌ 速度最慢(O(N))
- ❌ 不适合大数据量
性能数据:
- 1 万条数据,检索延迟:< 10ms
- 100 万条数据,检索延迟:~5000ms
适用场景:
- 数据量 < 1 万
- 精度要求极高
- 原型验证
📚 参考:Milvus:向量索引说明文档