DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

pgvector 建 HNSW 后,带过滤的 LIMIT 10 为什么只返回几条

近似索引先取候选,再过滤时可能不足 k。按 pgvector 0.8.0 对照精确结果和迭代扫描,测量返回数、召回与延迟,不把索引结果减少认定为数据丢失。

给向量列加 HNSW 索引后,原来能返回足够记录的查询变少了。先确认执行计划和过滤条件,别立即删除索引或重新灌数据。

pgvector issue #684记录过建索引后返回数量减少的现象。作者尝试删除 ORDER BY,维护者提醒这样已不再执行最近邻搜索。因此不能把“返回更多行”单独当作修复。

下面按 pgvector 0.8.0 的迭代扫描说明处理带过滤查询。旧版本没有这个功能,先核对运行数据库实际扩展版本:

SELECT extversion FROM pg_extension WHERE extname = 'vector';

判断不足 k,是候选减少还是匹配行本来就少

HNSW 先产生近似候选,再执行过滤。部分候选被 WHERE 排除后,LIMIT 10 并不要求索引自动找到十个符合条件的结果。

检查相同快照下到底有多少有效匹配行,以及过滤是否包括权限、租户或距离阈值。NULL 向量不进入索引,余弦索引也不收零向量;不存在十条有效匹配时,调参数不能制造十条业务记录。

以下是结构示例,假定表 items 已有 category_id 和三维 embedding,余弦 HNSW 索引也已建立。真实向量长度及条件须换成项目配置:

BEGIN;
SET LOCAL hnsw.iterative_scan = 'strict_order';
SELECT id, embedding <=> '[0.2,0.1,0.3]'::vector AS distance
FROM items
WHERE category_id = 123
ORDER BY embedding <=> '[0.2,0.1,0.3]'::vector
LIMIT 10;
COMMIT;

0.8.0 的迭代扫描会按需要继续找候选,但仍受扫描预算约束。返回顺序严格,不等于选出的近邻集合已经达到精确搜索召回率。

用相同条件建立精确对照

在有负载预算的测试环境中,对同一数据快照执行精确搜索,再比较 ID 集合和数量。可以在一次事务内暂时禁止普通 index scan,执行相同查询后结束事务;先查看计划,确认没有走近似索引:

BEGIN;
SET LOCAL enable_indexscan = off;
EXPLAIN
SELECT id
FROM items
WHERE category_id = 123
ORDER BY embedding <=> '[0.2,0.1,0.3]'::vector
LIMIT 10;
ROLLBACK;

EXPLAIN 本身只查看计划;测量实际输出和耗时时再执行查询。精确搜索可能更耗 CPU,不在高峰对全量大表反复运行。

调整 hnsw.ef_search、扫描上限或过滤列索引时,一次只改变一个因素,并记录召回与延迟。筛选值和数据分布变化后还需回归,不承诺某个固定参数适合所有负载。

验收包括:有效匹配行本来充足、查询返回数达到任务要求、召回和延迟符合标准,且过滤条件与权限边界保留。仅移除 WHERE 或 ORDER BY 得到更多记录,会改变业务问题。