首页/AI/RAG 与向量库速查/pgvector 距离算子与查询

pgvector 距离算子与查询

pgvector 用算子表达距离:<-> 欧氏距离、<=> 余弦距离、<#> 负内积;检索按 ORDER BY 距离排序取最近邻,配合 LIMIT 得到 top-k。

RAG 与向量库速查AI更新于 2026-10-13

pgvector 距离算子

pgvector 把向量检索表达成 SQL 里的距离运算:<-> 是欧氏距离,<=> 是余弦距离(等于 1 减余弦相似度),<#> 是负内积。检索写法固定为 ORDER BY 距离 LIMIT k——注意排序方向取决于算子本身的语义,越相似的候选距离越小。要走上索引,ORDER BY 中使用的算子必须与索引的算子类匹配,否则规划器只能退化成顺序扫描,数据量大时延迟会非常明显。

基本信息

扩展pgvector(vector / halfvec / sparsevec 等类型)
算子<-> 欧氏、<=> 余弦、<#> 负内积
典型写法ORDER BY embedding <=> $1 LIMIT 10
索引算子类vector_cosine_ops、vector_l2_ops、vector_ip_ops
匹配要求ORDER BY 的算子与索引算子类必须一致

典型使用场景

  • 已有 PostgreSQL 的团队做轻量 RAG:不引入新组件,向量与业务数据同库事务处理
  • 带权限与业务条件的检索:用普通 WHERE 条件叠加向量排序,天然支持复杂过滤
  • 混合排序:把向量距离与时间衰减、热度等业务字段一起算入最终排序
  • 迁移对照:把现有向量库的数据导入 pgvector,用同一评测集验证一致性
  • 小规模场景:几十万条向量配合 HNSW 索引即可满足多数内部应用

三种算子的检索写法

三种算子的检索写法
-- 余弦距离(结果为 1 - 余弦相似度,越小越相似)
SELECT id, 1 - (embedding <=> $1) AS cos_sim
FROM kb_chunks
ORDER BY embedding <=> $1
LIMIT 10;

-- 欧氏距离
SELECT id FROM kb_chunks ORDER BY embedding <-> $1 LIMIT 10;

-- 负内积(值越小越相似,注意是负数)
SELECT id FROM kb_chunks ORDER BY embedding <#> $1 LIMIT 10;

算子语义速查

算子含义排序方向
<->欧氏距离升序,值越小越相似
<=>余弦距离升序,值越小越相似
<#>负内积升序,负数绝对值越大越相似
1 - (<=>)余弦相似度降序,值越大越相似

上线前后检查项

  • 执行计划核对:EXPLAIN 看是否命中向量索引,避免悄悄退化成全表扫描
  • 归一化口径:确认入库与查询两侧一致,否则余弦与内积结论互相矛盾
  • 批量写入:用 COPY 或批量 INSERT 减少往返,写入时暂时调整维护参数
  • 回滚预案:索引重建耗时较长,保留旧索引名与切换脚本以便快速回退
<#> 返回的是负内积:ORDER BY 取最小值,把结果直接当相似度展示会出现负数,界面与阈值判断都要先做一次符号与偏移转换。

易错点

  • 把 <#> 的结果直接当相似度展示,界面上出现负值
  • 查询端归一化策略与入库时不一致,余弦与内积的排序结果对不上
  • ORDER BY 的算子与索引算子类不匹配,索引不生效走全表扫描,延迟成倍上升
  • 数据量还小时不加索引也能跑,上线后才补索引导致写入与查询同时拥塞
  • 在向量列上做类型转换(如转成 float8 数组)导致算子失效,索引完全用不上

数据来源与参考

  • pgvector README(Distance operators / Querying)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌