向量化数据库常用检索索引
索引的作用
向量数据库(VectorDB,如 Milvus、百度 VectorDB、Pinecone)的搜索速度快,核心是通过专门针对向量数据的设计优化,解决了「暴力检索(全量比对)速度慢」的问题,主要依赖以下 4 层优化逻辑:
一、核心问题:暴力检索的性能瓶颈
向量检索的本质是「计算查询向量与库中所有向量的相似度(如余弦距离、欧氏距离)」,若直接暴力检索:
假设库中有 1000 万条 768 维向量,暴力检索需计算 1000 万次向量相似度,单条查询耗时可达秒级甚至更久;
维度越高(如 1536 维)、数据量越大,耗时呈线性增长,完全无法支撑生产场景。
向量数据库的优化,就是围绕「减少需要计算相似度的向量数量」和「加速相似度计算」展开。
二、第一层优化:向量索引(核心提速逻辑)
向量数据库的核心提速依赖向量索引算法,通过「提前构建索引结构」,把全量比对变成「局部比对」,将检索复杂度从 O(n) 降到 O(log n) 或更低。
最常用的 3 类索引(也是搜索快的核心)
- HNSW 索引(分层导航小世界图)
原理:把向量构建成「多层图结构」,上层是稀疏的导航节点,下层是密集的细节节点;检索时先在上层快速定位到目标区域,再到下层精确查找,仅需比对数百~数千条向量(而非全量);
效果:1000 万条向量的检索耗时可降到 10~50ms,是目前生产环境中使用最多的索引(Milvus、百度 VectorDB 默认推荐)。
- IVF 索引(倒排文件索引)
原理:先把向量聚类成 N 个簇(Cluster),检索时先找到查询向量所属的簇,仅比对簇内的向量;
效果:检索耗时随簇数增加而降低,适合数据量极大(亿级)的场景。
- FLAT 索引(暴力检索,无优化)
仅用于小数据量(万级)测试,无索引优化,是性能基线。
三、第二层优化:存储与计算的硬件 / 架构优化
向量数据库针对向量数据的特性,做了底层硬件和架构的适配:
向量量化(压缩 + 加速计算)
四、第三层优化:检索逻辑的细节优化
除了索引和硬件,向量数据库还在检索的逻辑上做了优化:
提前过滤(标量 + 向量的复合优化)
五、第四层优化:针对生产场景的工程化优化
向量数据库还做了很多工程化的细节优化,进一步提升搜索速度:
批量检索优化
支持一次性提交多条查询向量(批量检索),复用索引和计算资源,比单条检索的总耗时更低;
索引的增量更新
支持在已有索引的基础上增量插入向量,无需重建整个索引,保证检索速度不随数据插入下降;
故障与负载的自动调度
分布式向量数据库会自动把检索请求调度到负载较低的节点,避免单节点过载导致的速度下降。
索引分类
|
维度 |
Scalar Index(标量索引) |
Vector Index(向量索引) |
Inverted Index(倒排索引) |
|
作用对象 |
结构化标量字段(INT/FLOAT/DATETIME/VARCHAR/BOOL 等) |
高维向量字段(FLOAT_VECTOR / 二进制向量) |
文本字段(VARCHAR/TEXT) |
|
核心检索目标 |
精确匹配 / 范围过滤(如 age>20、dept="技术部") |
相似性检索(如 Top-K 余弦相似度匹配) |
关键词 / 全文匹配(如 content:大模型 AND 知识管理) |
|
典型算法 / 类型 |
B-Tree、Hash、Range Index、Geo Index(地理坐标) |
HNSW、IVF_FLAT、FAISS Flat、Annoy |
倒排列表(Posting List)、BM25/TF-IDF(权重计算) |
|
检索精度 |
100% 精确 |
近似(ANN)/ 精确(Flat) |
精确(关键词匹配)/ 模糊(全文检索) |
|
核心优势 |
快速过滤结构化条件,缩小检索范围 |
亿级高维向量毫秒级相似性检索 |
高效支撑文本关键词 / 全文检索,适配自然语言查询 |
|
典型使用场景 |
业务属性过滤(部门、时间、价格、状态) |
以图搜图、RAG 语义检索、推荐系统 |
文档关键词检索、商品标题搜索、日志全文检索 |
详细介绍
1. Scalar Index(标量索引)
以最常用的 B-Tree 为例:
原理:将标量值按有序树结构存储,每层节点记录 “范围边界”,查询时从根节点向下快速定位目标值(如查 CreateTime>2025-01-01 时,直接跳过 2025 年前的节点);
适用字段:数值、时间、枚举型文本(如部门);
补充:Hash 索引适合 “精确等值匹配”(如 id=123),查询时间复杂度 O (1),但不支持范围查询。
2. Vector Index(向量索引)
以主流的 HNSW 为例:
原理:构建分层导航小世界图,高层节点做全局快速导航,底层节点做局部精细匹配,将高维向量的暴力检索(O (n))优化为 O (log n);
适用字段:768/1536/2048 维等高维向量(文本 / 图像 Embedding);
补充:Flat 索引是暴力检索(100% 精确),但仅适合小数据集(百万级以内)。
3. Inverted Index(倒排索引)
原理:先将文本拆分为关键词(分词),再构建 “关键词→文档 ID 列表” 的映射表(倒排列表);查询时先找到关键词对应的文档 ID,再过滤结果(如查 “大模型”,直接取所有包含该关键词的文档 ID);
适用字段:长文本、标题、描述等;
补充:结合 BM25/TF-IDF 计算关键词权重,提升全文检索的相关性排序精度。
向量索引
IVF(倒排文件索引)和 HNSW(分层导航小世界图)是向量检索领域最主流的两类核心算法,分别代表「聚类分治」和「图结构导航」两种核心思路,适配不同数据规模、性能需求和资源约束场景。以下从核心原理、性能特征、适用场景等维度做深度对比,附调优和选型建议:
核心本质区别:
|
维度 |
IVF(含 IVF_FLAT/PQ/SQ) |
HNSW(分层导航小世界图) |
|
核心思想 |
「分而治之」:通过聚类将向量空间划分为多个桶,检索时仅在目标桶内计算相似度 |
「图结构导航」:构建多层稀疏图,上层粗导航、下层精检索,快速定位相似向量 |
|
索引结构 |
聚类中心 + 倒排映射(桶 ID → 向量列表),可选叠加量化(PQ/SQ)压缩 |
多层有向图:每层是基于向量相似度的邻接表,顶层仅少量节点,底层包含所有节点 |
|
检索逻辑 |
1. 计算查询向量与所有聚类中心的距离,选 nprobe 个近桶;2. 桶内计算向量相似度(暴力 / 量化 / 子索引);3. 排序返回 Top-K |
1. 从顶层随机节点开始,贪心找近邻节点,逐层下沉;2. 底层做局部精检索(ef 参数控制范围);3. 排序返回 Top-K |
|
核心计算 |
聚类中心匹配(向量距离) + 桶内相似度计算(浮点 / 量化) |
图节点跳转(向量距离) + 局部邻域遍历 |
关键性能指标
关键性能指标对比(基准:1 亿条 768 维向量,CPU 集群)
|
性能指标 |
IVF_PQ(兼顾速度 / 存储) |
IVF_FLAT(无精度损失) |
HNSW(默认参数) |
|
查询延迟 |
10~30ms |
50~100ms |
5~20ms(极致快) |
|
召回率 |
90%~98%(量化有损失) |
100%(无损失) |
95%~99%(无量化损失) |
|
索引构建耗时 |
快(分钟级,K-Means 聚类) |
快(分钟级) |
慢(小时级,多层图构建) |
|
存储开销 |
低(量化后仅占原始 1/8~1/16) |
高(原始向量 + 聚类中心) |
极高(原始向量 + 图结构,比原始多 20%~50%) |
|
并发 QPS |
5000~15000(单节点) |
1000~2000(单节点) |
5000~10000(单节点) |
|
数据更新性能 |
插入快(增量聚类 / 标记),删除需异步清理 |
插入快,删除慢 |
插入 / 删除慢(需更新图结构) |
|
维度适配性 |
适配高维(1024+),量化后优势更明显 |
中低维(≤1024)性能最优,高维速度下降 |
总结
IVF 和 HNSW 的核心差异可归纳为:
IVF:「聚类分治 + 可选量化」,适配超大规模、存储受限、高维向量,速度中等,召回可精准调优;
HNSW:「图结构导航」,适配千万~亿级、内存充足、低延迟需求,速度极致,召回率高但内存开销大;
混合方案 IVF_HNSW:兼顾两者优势,是生产环境「万金油」选择。
代码示例
- 标量查询
primaryKey = {}
primaryKey['DocId'] = "37a9523d-3afb-f576-91ad-7075d6e3c8eb"
partitionKey = {}
partitionKey['Department'] = "技术部"
results = table.query(primary_key=primaryKey, partition_key=partitionKey)
print("Query result: {}".format(results))
- 向量检索
# 向量检索
vectorFloats = [0.12123456, 0.41840295]
anns = AnnSearch(vector_field="Vector", vector_floats=vectorFloats,
filter="Department == '运营部'",
params=HNSWSearchParams(ef=200, limit=2))
result = table.search(anns=anns, retrieve_vector=True)
print("Search result: {}".format(result))
- 倒排索引检索
request = BM25SearchRequest(index_name="title_content_inverted_index", search_text="title:科比.布莱恩特", limit=10) res = table.bm25_search(request=request) logger.debug("BM25 search res: {}".format(res))
1426

被折叠的 条评论
为什么被折叠?



