空表上先建了 ivfflat 索引再灌 80 万条向量,查询 recall@10 只有 0.41,重建索引后同一个参数下回到 0.93。
一开始怀疑是「建完没执行 ANALYZE,规划器统计信息过期」,查了一圈,方向不对。
这类报错背后常见的原因有几处,逐个排除就行。ivfflat 的聚类中心在建索引时就固定,空表建出来没有意义。还有一种是数据量增加后 lists 与行数的比例严重失衡。
少数情况下是查询走了顺序扫描,索引压根没被用上。
动手时先确认执行计划有没有走索引
psql -d kb -c "EXPLAIN ANALYZE SELECT id FROM docs ORDER BY emb <-> '[0.1,0.2]' LIMIT 10;"
再往下按行数重设 lists 后重建索引
psql -d kb -c "DROP INDEX IF EXISTS docs_emb_idx; CREATE INDEX docs_emb_idx ON docs USING ivfflat (emb vector_cosine_ops) WITH (lists = 800);"
补一次统计信息
psql -d kb -c "ANALYZE docs;"
等前面都确认过,再设 probes 后再量一次召回
psql -d kb -c "SET ivfflat.probes = 10; SELECT count(*) FROM (SELECT id FROM docs ORDER BY emb <-> '[0.1,0.2]' LIMIT 10) t;"
白天有业务在跑,能验证的部分都压到了晚上做。
别只看报错消失,验证要多做一步。EXPLAIN 显示走 Index Scan,recall@10 从 0.41 回到 0.9 以上,probes 调到 10 时延迟仍在 20 毫秒内。
这里还有个坑。ivfflat 必须在数据灌满后建,之后大批量写入还要重建;HNSW 没这个限制但建索引更慢。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
