首页/AI/RAG 与向量库速查/pgvector 与 SQL 混合检索

pgvector 与 SQL 混合检索

pgvector 的独特优势是向量近邻与关系条件在同一句 SQL:WHERE 过滤、JOIN 业务表、全文检索 tsvector 都能与向量排序组合,用一条语句完成多条件召回。

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

为什么在 SQL 里做混合

pgvector 的独特优势是向量近邻与关系条件写在同一句 SQL 里:WHERE 过滤、JOIN 业务表、全文检索(tsvector)都能与向量排序组合,一条语句完成多条件召回。省掉了「向量库与业务库之间对账」的麻烦,也能直接复用已有的权限控制与事务能力,适合文档量中等、已有 PostgreSQL 技术栈的团队。

基本信息

前提PostgreSQL 安装 pgvector 扩展,向量列类型为 vector
距离操作符<-> 表示 L2,<=> 表示余弦,<#> 表示内积
混合方式先过滤或先关键词检索缩小候选,再按向量距离排序
性能关键过滤条件的选择性,以及向量索引是否被正确命中

典型使用场景

  • 权限与状态过滤:只检索已发布且在有效期内、用户有权限的文档
  • 与业务表联动:JOIN 文档主表取标题与链接,回答里直接展示来源
  • 中文关键词补充:型号与错误码用全文检索精确命中,语义问题交给向量
  • 一次开发两用:同一套 SQL 既做后台检索,也做在线问答的召回
  • 小规模团队选型:不引入独立向量库即可支撑十万级切片

过滤与向量排序

过滤与向量排序
SELECT c.id, c.content
FROM kb_chunks c
JOIN kb_docs d ON d.id = c.doc_id        -- 关联业务表取权限与状态
WHERE d.status = 'published'
  AND d.updated_at >= now() - interval '90 days'
ORDER BY c.embedding <=> $1              -- 余弦距离,越小越相似
LIMIT 10;
-- 过滤条件选择性高时,数据库会先做过滤再排序,效率通常更好

全文检索两段式

全文检索两段式
WITH kw AS (
  SELECT id FROM kb_chunks
  WHERE to_tsvector('simple', content) @@ plainto_tsquery('simple', $2)
  LIMIT 50                               -- 先缩候选,避免全表向量比较
)
SELECT c.id FROM kb_chunks c
WHERE c.id IN (SELECT id FROM kw)
ORDER BY c.embedding <=> $1 LIMIT 10;

两种两段式写法

写法执行顺序适用情况
过滤加向量排序先按条件过滤再排序过滤选择性高、候选集小
全文检索加向量排序先关键词缩候选再向量排序型号、错误码等专有名词查询
子查询内排序再过滤排序后过滤,语义错误不推荐,会漏掉应命中结果
JOIN 业务表按权限与状态过滤需与业务状态联动的场景
过滤条件的选择性决定执行计划:高选择性过滤先行、再做向量排序通常更划算,必要时用 EXPLAIN 确认索引有没有被用上。
用 EXPLAIN 或 EXPLAIN ANALYZE 看计划,比凭感觉调 SQL 可靠:能看到是全表扫描还是走了索引,也能看到过滤实际剩多少行。

易错点

  • 把向量排序写在子查询内再过滤,语义上过滤在排序之后执行
  • 中文全文检索未配分词扩展,tsvector 按空格切分几乎不命中
  • 向量索引与过滤条件配合不当,优化器改走全表扫描导致延迟飙升
  • 单句 SQL 里 JOIN 过多大表,检索延迟被无关关联拖慢

数据来源与参考

  • pgvector README(Hybrid Search)
  • PostgreSQL 官方文档(全文检索 / EXPLAIN)
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌