如何构建和使用向量索引?HNSW 和 IVF 有什么区别?

如何构建和使用向量索引?HNSW 和 IVF 有什么区别?

如何构建和使用向量索引?HNSW 和 IVF 有什么区别?

向量索引是什么?

在RAG系统中,向量数据库里存储的文档块(Chunks)可能有成百上千万个。向量索引就是一种特殊的数据结构 ,它的作用是让你不必每次查询都扫描全部数据,而是能像查字典一样,快速定位到最相关的那些向量。

如果把暴力搜索比作"在图书馆里一本一本地翻书",那么:

  • IVF索引 = 先把书按类别分到不同书架,你直接去"历史区"找,不用逛遍全馆
  • HNSW索引 = 图书馆里修了一条条"快速通道",让你能沿着路标跳跃式直达目标

这两种都是近似最近邻搜索(ANN)算法,通过牺牲微乎其微的精度,换来几十上百倍的速度提升。


一、IVF索引:先聚类,再搜索

IVF的核心思想是借鉴了文本检索里的"倒排索引"------把相似的向量预先分到同一个"桶"里。

构建过程(离线阶段)

步骤 做什么 类比
1. 聚类训练 用 K-Means 算法把数据集分成 nlist 个簇,每个簇有一个中心点 决定图书馆分几个区
2. 建立倒排表 把每条向量分配到离它最近的中心点所属的簇 把书放到对应书架上
3. 压缩编码(可选) 对每个簇内的向量做压缩,如PQ(乘积量化)、SQ8(标量量化) 给书做索引卡

构建完成后,你会得到一个质心表 + 多个倒排列表的结构。

查询过程(在线阶段)

复制代码
用户查询向量 q
    │
    ▼
1. 计算 q 到所有质心的距离,排序
    │
    ▼
2. 选择距离最近的 nprobe 个簇(只在这几个桶里搜)
    │
    ▼
3. 在这些簇内做精确/近似距离计算
    │
    ▼
返回 Top-K 结果

这个过程就像一个高效图书馆员:读者进门后,先判断"你要的书可能在历史区或文学区",然后只在这两个区域里仔细找,不用逛遍全馆。

IVF 的三种常见变体

变体 特点 内存占用 召回率 适用场景
IVF_FLAT 无压缩,存储原始向量 最高(95%+) 中等数据量,精度优先
IVF_SQ8 标量量化压缩(4:1) 高(90%+) 大规模数据,平衡精度
IVF_PQ 乘积量化压缩(最高64:1) 极低 中(70-90%) 超大规模,内存紧张

二、HNSW索引:多层导航图

HNSW的全称是 Hierarchical Navigable Small World (分层可导航小世界)。它的核心是构建一个多层图结构

  • 最底层:包含所有数据点,连接最密集
  • 往上层:每层只保留上一层的部分点,连接稀疏
  • 最顶层:只有少量"地标点",连接最少

查询时,从上往下逐层导航:

  1. 从顶层开始,快速跳到离查询向量最近的区域
  2. 到下一层继续细化
  3. 直到最底层,找到最终的近邻

你可以把它想象成一个高速公路系统:在顶层走高速快速到达城市附近,下到地方道路后慢慢找具体地址。

HNSW 的关键参数

参数 含义 调参建议
M 每层每个节点的最大连接数 默认16,越大越准但越耗内存
ef_construction 构建时的候选列表大小 默认200,越大越准但构建越慢
ef_search 搜索时的候选列表大小 默认10,越大越准但查询越慢

三、IVF vs HNSW:全方位对比

对比维度 IVF HNSW
核心思想 聚类分桶 多层图导航
内存占用 较低 较高(需将整个索引加载到内存)
索引构建速度 快(只需聚类) 慢(需建多层图)
查询速度(无过滤) 快���依赖 nprobe 极快,对数级复杂度
查询速度(带过滤) (质心层面先筛选) 差(过滤比例高时几乎全图遍历)
召回率 高(非量化可达95%+) 更高(通常98%+)
延迟分布 相对稳定,取决于簇大小 波动较大,受查询路径影响
是否需预训练 是(需K-Means聚类) 否(可空表建索引)
数据更新代价 较低(增量插入) 较高(图结构需重构)

四、如何选择?一张决策表

你的场景 推荐索引 原因
通用RAG,数据量百万级以内 HNSW 查询速度最快,召回率最高
数据量超大(亿级+),内存有限 IVF_PQ 压缩率高,内存可控
查询常带过滤条件(如按用户ID、时间范围) IVF 过滤场景下性能更稳定
追求极致的查询速度,内存充足 HNSW 对数级检索,毫秒响应
需要频繁插入新数据 IVF 增量更新代价更小
首次搭建,想快速验证 IVF_FLAT 构建快,参数少,效果好

数据量级参考建议

数据量 推荐方案
< 10万 甚至不需要索引,暴力搜索即可
10万 ~ 100万 IVF_FLAT 或 HNSW 均可
100万 ~ 1000万 HNSW(内存充足)或 IVF_SQ8(内存有限)
> 1000万 IVF_PQ(内存优先)或 IVF_SQ8(精度优先)

五、关键参数调优

IVF 参数

参数 含义 调优经验
nlist 聚类数量(构建时固定) 约等于 √N(N为向量数)。100万向量取1000左右
nprobe 搜索时探测的簇数(查询时可调) 从1-16逐步试探,找到延迟与召回率的平衡点

HNSW 参数

参数 含义 调优经验
M 每层最大连接数 默认16,对精度要求高可调至32-64
ef_construction 构建时候选列表大小 默认200,越大越准但构建越慢
ef_search 查询时候选列表大小 默认40,越大召回率越高但延迟增加

六、使用示例

以下是在流行向量数据库中的配置方式:

Milvus / PyMilvus

python 复制代码
# IVF_FLAT 索引
index_params = {
    "index_type": "IVF_FLAT",
    "metric_type": "COSINE",
    "params": {"nlist": 1024}
}

# HNSW 索引
index_params = {
    "index_type": "HNSW",
    "metric_type": "COSINE",
    "params": {"M": 16, "efConstruction": 200}
}

pgvector (PostgreSQL)

sql 复制代码
-- HNSW 索引
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);

-- IVFFlat 索引
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops)
WITH (lists = 1000);

-- 查询时设置 probes
SET ivfflat.probes = 10;

总结

IVF 像图书馆的"分类书架"------先确定在哪个区,再细找。

HNSW 像高速公路导航系统------从上到下,逐层精确定位。

  • HNSW:查询更快、召回率更高,但内存占用大,构建慢
  • IVF:内存友好、过滤场景稳定,构建快,但查询精度略低

对于绝大多数RAG应用(百万级向量、内存充足),HNSW通常是更好的起点 。如果数据量达到亿级或内存受限,则考虑IVF_PQ

pgvector 是什么?

pgvector 是 PostgreSQL 的向量相似度搜索扩展。它的核心价值是:让你可以在关系型数据库里直接做向量检索,无需额外维护一套独立的向量数据库

这意味着你的业务数据(用户表、订单表)和向量数据(文档 Embedding)可以放在同一个数据库里,用同一种 SQL 语法操作,还能享受 PostgreSQL 的 ACID 事务、时间点恢复、多表 JOIN 等企业级特性。


一、pgvector 支持哪些向量类型?

pgvector 支持 4 种向量类型,各有不同的存储开销和适用场景:

向量类型 存储开销 维度上限 适用场景
vector(单精度) 4 × 维度 + 8 字节 16,000 通用场景,精度最高
halfvec(半精度) 2 × 维度 + 8 字节 16,000 精度要求不高、希望节省内存
bit(位向量) 维度 / 8 + 8 字节 64,000 二进制向量(如哈希签名)
sparsevec(稀疏向量) 8 × 非零元素数 + 16 字节 16,000 个非零元素 大部分元素为 0 的高维向量

实际建议 :大多数 RAG 场景直接用 vector 类型即��,维度通常在 384-1536 之间,存储开销完全可以接受。


二、pgvector 支持的距离度量

pgvector 提供了 6 种距离操作符,覆盖了主流相似度计算需求:

操作符 距离类型 说明
<-> 欧几里得距离(L2) 越小越相似
<=> 余弦距离 越小越相似,相似度 = 1 - 余弦距离
<#> 内积 返回负内积(因 PostgreSQL 只支持升序)
<+> 曼哈顿距离(L1) 绝对值距离
<~> 汉明距离 仅用于 bit 向量
<%> Jaccard 距离 仅用于 bit 向量

查询示例(找与查询向量最相似的 5 条记录):

sql 复制代码
SELECT * FROM items
ORDER BY embedding <=> '[0.1, 0.2, ...]'
LIMIT 5;

三、支持的索引类型:HNSW vs IVFFlat

pgvector 支持两种近似最近邻(ANN)索引:HNSWIVFFlat。两者的核心区别如下:

对比维度 HNSW IVFFlat
工作原理 构建多层导航图 用 K-Means 把向量空间分成多个"桶"
是否需要训练 是------需要先有代表性数据做聚类
索引构建速度 慢(需要建图) 快(只需聚类 + 分配)
查询速度 极快(对数级) 较快
召回率 更高(98%+) 较高(参数调优后可达 95%+)
内存占用 较高(需存储整个图) 较低(只存簇中心和倒排列表)
对数据分布敏感度 高------数据变化后需重建索引
支持的最大索引维度 ~2,000 ~2,000(vector 类型)

核心选择建议

场景 推荐索引 原因
追求查询速度和召回率,内存充足 HNSW 查询最快,召回率最高
向量频繁更新、内存有限 IVFFlat 构建快、内存小
百万级以内数据量 HNSW 简单,效果好
千万级以上、内存紧张 IVFFlat + 半精度量化 压缩率高,内存可控

四、HNSW 索引的创建与参数调优

创建 HNSW 索引

sql 复制代码
-- 使用 L2 距离
CREATE INDEX ON items USING hnsw (embedding vector_l2_ops)
WITH (m = 16, ef_construction = 64);

-- 使用余弦距离
CREATE INDEX ON items USING hnsw (embedding vector_cosine_ops)
WITH (m = 16, ef_construction = 64);

关键参数

参数 含义 默认值 调优建议
m 每个节点的最大连接数 16 越大→图越密→召回率↑,但内存↑、构建↓
ef_construction 构建时的候选列表大小 64 越大→召回率↑,但构建时间显著↑
ef_search 查询时的候选列表大小(运行时设置) 10 越大→召回率↑,但查询延迟↑

运行时调整 ef_search

sql 复制代码
SET hnsw.ef_search = 200;  -- 查询前设置
SELECT * FROM items ORDER BY embedding <=> '[0.1, ...]' LIMIT 10;

五、IVFFlat 索引的创建与参数调优

创建 IVFFlat 索引

sql 复制代码
CREATE INDEX ON items USING ivfflat (embedding vector_l2_ops)
WITH (lists = 100);

关键参数

参数 含义 调优建议
lists 聚类中心数(构建时固定) 约为 √(向量总数),100 万条取 1000 左右
probes 查询时搜索的簇数(运行时设置) 越大→召回率↑,延迟↑。从 10 开始逐步测试

⚠️ 重要 :IVFFlat 索引必须先有数据再创建,因为需要通过 K-Means 学习数据的分布。

运行时调整 probes

sql 复制代码
SET ivfflat.probes = 10;  -- 会话级别
SELECT * FROM items ORDER BY embedding <=> '[0.1, ...]' LIMIT 10;

六、pgvector 的核心优势与局限性

优势

优势 说明
与 PostgreSQL 无缝集成 向量数据可以和业务数据在同一张表、同一事务中操作
标准 SQL 语法 无需学习新 API,ORDER BY + LIMIT 即可检索
ACID 事务 向量索引与表数据保持一致,支持回滚
企业级功能 时间点恢复、主从复制、多表 JOIN、行级安全
生态成熟 支持所有 PostgreSQL 客户端和 ORM 框架
开源免费 无额外许可费用

局限性

局限性 说明 影响程度
8KB 页面限制 向量过大时无法有效索引。建议索引维度 ≤ 2000
分布式能力弱 原生不支持水平分片,大规模需手动分片
过滤性能差 无法在向量检索时高效下推 metadata 过滤条件
索引类型有限 只有 HNSW 和 IVFFlat,缺少 DiskANN 等更先进的索引
GPU 加速不支持 纯 CPU 计算

七、选择建议:pgvector vs 专用向量数据库

场景 推荐方案 原因
数据量 < 100 万,已在用 PostgreSQL pgvector 零额外运维成本,性能足够
需要 ACID 事务、多表 JOIN pgvector 专用向量数据库这些能力弱
不想引入新组件,降低架构复杂度 pgvector 一套数据库解决所有问题
数据量 > 500 万,查询 QPS 高 专用向量数据库(Milvus/Qdrant) 分布式能力、GPU 加速
需要复杂的 metadata 过滤 专用向量数据库 pgvector 过滤性能差
混合检索(向量 + 全文检索) 两者结合 pgvector 可结合 PostgreSQL 全文检索

快速开始(完整示例)

sql 复制代码
-- 1. 安装扩展
CREATE EXTENSION IF NOT EXISTS vector;

-- 2. 创建表
CREATE TABLE documents (
    id SERIAL PRIMARY KEY,
    title TEXT,
    content TEXT,
    embedding vector(384)  -- 根据你的模型维度
);

-- 3. 创建 HNSW 索引
CREATE INDEX ON documents USING hnsw (embedding vector_cosine_ops);

-- 4. 插入数据
INSERT INTO documents (title, content, embedding)
VALUES ('年假政策', '公司年假每年15天', '[0.12, -0.34, ...]');

-- 5. 语义检索
SELECT title, content,
       1 - (embedding <=> '[0.11, -0.33, ...]') AS similarity
FROM documents
ORDER BY embedding <=> '[0.11, -0.33, ...]'
LIMIT 5;

总结

pgvector 的核心价值是把 PostgreSQL 变成"能理解语义的关系数据库"。它让向量检索不再是独立系统的专利,而是关系型数据库的一个自然扩展。

对于大多数 RAG 应用(数据量百万级以内),pgvector 是完全够用的选择,而且能极大简化架构。如果未来数据量暴增,再考虑迁移到专用向量数据库也不迟。

SELECT title, content,

1 - (embedding <=> '0.11, -0.33, ...') AS similarity

FROM documents

ORDER BY embedding <=> '0.11, -0.33, ...'

LIMIT 5;

复制代码
---

## 总结

**pgvector 的核心价值是把 PostgreSQL 变成"能理解语义的关系数据库"**。它让向量检索不再是独立系统的专利,而是关系型数据库的一个自然扩展。

对于大多数 RAG 应用(数据量百万级以内),pgvector 是完全够用的选择,而且能极大简化架构。如果未来数据量暴增,再考虑迁移到专用向量数据库也不迟。
相关推荐
counting money2 小时前
Java IO流详解:从InputStream到文件操作实战
java·开发语言·python
坚持学习前端日记3 小时前
Python SQLAlchemy ORM 从0到1精通实战手册(基础到复杂高阶)
数据库·python·oracle
蜡台3 小时前
大模型算力下放客户端:浏览器/本地设备全落地方案解析
人工智能·ai
北斗落凡尘3 小时前
LangGraph 入门实战(11)--输出模式
后端·python·langchain
土星云SaturnCloud3 小时前
产线SOP动作级AI监管方案:土星云SE110S-WC8赋能合规识别、预警与效率分析
大数据·服务器·人工智能·ai·边缘计算
李燚3 小时前
HITL 源码:8 种人机协同模式的设计(第85篇-E71)
ai·agent·ai编程·模式·rag·eino·hitl
雪碧聊技术4 小时前
安装Python(保姆级教程)
python·版本更新·python下载
++==4 小时前
JSON和Python的 四种核心容器
python·json