向量数据库实战:选型、调优与落地~系列文章05:IVF、PQ、ScaNN 索引对比:大规模数据下的性能与内存博弈

发布时间:2026/7/17 12:46:06
向量数据库实战:选型、调优与落地~系列文章05:IVF、PQ、ScaNN 索引对比:大规模数据下的性能与内存博弈 IVF、PQ、ScaNN 索引对比大规模数据下的性能与内存博弈 ⚖️本文是《向量数据库实战选型、调优与落地》专栏第 05 篇⏱️阅读时间约 13 分钟 开篇HNSW 搞不定的场景上一篇我们夸了 HNSW 半天但它也有致命弱点内存占用大1 亿条 1024 维向量HNSW 需要 ~500GB 内存 构建速度慢数据量越大构建索引越慢不适合超大规模千万级以上数据单机基本扛不住怎么办这时候就需要 IVF、PQ、ScaNN 这些大规模数据专用索引出场了 IVF倒排文件索引核心思想IVFInverted File Index的思路非常直觉类比图书馆找书 暴力搜索从第一本书开始一本一本翻O(N) IVF先把书按类别分到不同书架先找到对的书架再在书架里找 步骤 1. 训练阶段用 K-Means 把向量空间分成 nlist 个簇Voronoi cells 2. 索引阶段每个向量分配到最近的簇中心 3. 查询阶段只搜索查询向量最近的 nprobe 个簇结构图解┌─────────────────────────────────────────────────────────┐ │ IVF 索引结构 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 训练后的簇中心nlist4: │ │ │ │ C1 ● C2 ● │ │ ╱ ╲ ╱ ╲ │ │ ╱ ● ╲ ● ╱ ● ╲ │ │ ╱ ● ╲ ╱ ● ╲ │ │ ● ● ● ● ● ● │ │ │ │ C3 ● C4 ● │ │ ╱ ╲ ╱ ╲ │ │ ╱ ● ╲ ● ╱ ● ╲ │ │ ╱ ● ╲ ╱ ● ╲ │ │ ● ● ● ● ● ● │ │ │ │ 查询★ 落在 C1 和 C2 的边界 │ │ → 只搜索 nprobe2 个最近的簇C1 和 C2 │ │ → 计算量从 N 降到 N/2 │ │ │ └─────────────────────────────────────────────────────────┘关键参数参数含义推荐值影响nlist簇的数量sqrt(N) ~ 4*sqrt(N)越大 → 精度↑ 但每个簇数据越少nprobe查询时搜索的簇数nlist 的 1%~10%越大 → 召回率↑ 速度↓内存估算IVF 内存 ≈ 向量数据本身 簇中心 N × 维度 × 4 bytes nlist × 维度 × 4 bytes 示例1 亿条 1024 维nlist10000 100,000,000 × 1024 × 4 10,000 × 1024 × 4 ≈ 400 GB 40 MB ≈ 400 GB簇中心几乎不占内存⚠️ 注意纯 IVF 的内存和暴力搜索差不多它主要优化的是查询速度不是内存。要省内存需要搭配 PQ。 PQ乘积量化核心思想PQProduct Quantization的核心是压缩——把高维向量压缩成短编码大幅降低内存。类比用邮编代替完整地址 原始地址北京市海淀区中关村大街 1 号20 个字 邮编1000806 个数字 虽然精度降低了但大部分场景够用而且存储成本降了 90% PQ 的原理 1. 把 1024 维向量切成 M 个子向量如 64 段每段 16 维 2. 每段独立做 K-Means 聚类通常 K256 3. 每个子向量用 1 个 byte 的聚类编号代替 4. 1024 维 → 64 bytes压缩 64 倍压缩效果┌─────────────────────────────────────────────────────────┐ │ PQ 压缩示意 │ ├─────────────────────────────────────────────────────────┤ │ │ │ 原始向量1024 维 float32: │ │ [0.12, -0.34, 0.56, ..., 0.23] │ │ 大小1024 × 4 4096 bytes │ │ │ │ ↓ PQ 编码M64 子空间每子空间 256 个聚类中心 │ │ │ │ 编码向量: │ │ [42, 128, 7, 201, 55, ..., 89] │ │ 大小64 × 1 64 bytes │ │ │ │ 压缩比4096 / 64 64 倍 │ │ │ │ 内存对比1 亿条向量: │ │ 原始400 GB │ │ PQ 6.4 GB ← 省了 98.4% │ │ │ └─────────────────────────────────────────────────────────┘关键参数参数含义推荐值约束M子空间数量64~256必须能整除向量维度nbits每个子空间的编码位数8默认2^nbits 每段聚类数PQ 的代价压缩是有代价的——精度会下降压缩比召回率10适用场景8xM128~92%内存充足追求精度16xM64~88%平衡选择32xM32~82%内存紧张64xM16~75%极度内存敏感 IVF PQ最强组合实际生产中IVF 和 PQ 几乎总是一起使用IVF_PQ IVF加速搜索 PQ压缩内存 效果 - 查询速度比纯 PQ 快IVF 先缩小范围 - 内存占用比纯 IVF 低PQ 压缩向量 - 召回率略低于纯 IVF但可接受内存对比索引类型1亿条 1024维 内存查询延迟召回率10Flat暴力~400 GB~500ms100%IVF~400 GB~50ms~95%PQ~6.4 GB~30ms~88%IVF_PQ~6.4 GB~15ms⚡~90%HNSW~520 GB~8ms~97% ScaNNGoogle 的黑科技核心思想ScaNNScalable Nearest Neighbors是 Google 在 2020 年提出的算法结合了多种技术的优点。ScaNN 各向异性量化Anisotropic Quantization 预筛选Pre-scoring 重排序Re-scoring 核心创新 传统 PQ 追求向量重建误差最小 ScaNN 追求内积估计误差最小直接优化最终目标ScaNN vs PQ对比维度PQScaNN量化目标最小化重建误差最小化内积误差同压缩比下召回率88%93%✅是否支持重排序❌✅用原始向量重排 Top-K开源是✅Google 开源生态支持广泛较少主要在 FAISS/ScaNN 库 四大索引全面对比维度HNSWIVFIVF_PQScaNN查询速度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐召回率⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐内存效率⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐构建速度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐动态插入✅❌❌❌适合数据量1000万100万1000万100万训练需求无需需要需要需要磁盘支持部分✅✅✅ 选型决策矩阵你的数据量是多少 │ ├── 100 万 │ └── HNSW简单、效果好、支持动态插入 │ ├── 100 万 ~ 1000 万 │ ├── 内存充足50GB → HNSW │ └── 内存有限 → IVF_PQnlist1000, M64 │ ├── 1000 万 ~ 1 亿 │ ├── 需要动态插入 → HNSW分布式 │ └── 静态数据 → IVF_PQnlist10000, M64 │ └── 1 亿 ├── 追求精度 → IVF_PQ 重排序 └── 追求极致 → ScaNN 分布式 代码实战Milvus 中配置 IVF_PQfrompymilvusimportCollection,DataType# IVF_PQ 索引配置index_params{index_type:IVF_PQ,metric_type:COSINE,params:{nlist:1024,# 簇数量约 sqrt(100万) ≈ 1000m:64,# PQ 子空间数必须整除维度nbits:8# 每个子空间编码位数}}collection.create_index(embedding,index_params)# 查询时设置 nprobesearch_params{metric_type:COSINE,params:{nprobe:64}# 搜索 64 个最近的簇} 本篇核心要点回顾要点说明IVF分簇加速搜索但不省内存PQ压缩向量省内存但精度下降IVF_PQ两者结合大规模数据的标配ScaNNGoogle 出品同压缩比下精度更高选型核心数据量 内存预算 精度要求✍️ 写在最后没有最好的索引算法只有最合适的。记住这个公式小数据 高精度 → HNSW大数据 内存紧 → IVF_PQ超大数据 极致性能 → ScaNN下篇预告《Milvus 2.x 入门实战从安装到第一次相似度查询 》有问题欢迎评论区讨论觉得有用请点赞收藏 作者高炉炼铁智能化技术研究者专注钢铁冶金与人工智能 交叉领域。 如果觉得有帮助请点赞、收藏、转发版权归作者所有未经许可请勿抄袭套用商用(或其它具有利益性行为)。 关注专栏不错过后续精彩内容