日期:2026-09-20
我们知识库文档有几十万篇,但日活查询并不高,峰值也就几百 QPS。一开始按惯例上了 Milvus 集群,结果运维同学天天被召回抖动和节点扩容折腾,成本也下不来。我们回头想,规模没到那个量,硬上专用向量库是过度设计。
Milvus 集群那阵子,光是节点扩容和召回抖动就占了 DBA 大半精力,而我们查询量根本不配养这么重的组件,成本高还伺候不起。我们才下决心迁回轻量方案,把资源花在召回质量而不是集群运维上,方向才算正。
DBA 接管 pgvector 后,备份容灾直接复用现有 Postgres 体系,不用再为向量集群单独建一套,运维心智负担小了一大半。出事也有人能救,夜里睡得着,故障演练也敢真做。
我们把向量检索迁到 pgvector,和已有的业务库共用一套 Postgres,省掉一整套集群。场景是客服知识库的语义检索:用户问句向量化后,在 pgvector 里做近邻检索,再和关键词检索做混合,最后接重排。热词和高频问法我们加了缓存,命中就直接返回。
迁移到 pgvector 我们没一步切,先双写比对召回质量,确认持平才切流量,整个过程业务无感,这也是我们做技术切换的稳妥做法。DBA 本来就管 Postgres,不用再学一套向量集群,出问题有人管比新潮更重要。
混合检索上线后,我们补了一层同义词扩展,用户说口语化问法也能命中,客服反馈答非所问少了,这块是关键词检索兜的底。纯向量会漏,组合才稳,召回质量才真的上来。
我们后来把这套轻量向量方案沉淀成标准模板,新业务要接语义检索直接套,不用再纠结上不上专用集群,DBA 也熟悉,出问题自己能排。技术栈统一后维护成本反而更低,新人上手也快,复制成本几乎为零。迁移时我们留了 Milvus 对比报表给老板,召回持平成本砍半,老板才信轻量不是凑合。技术选型用数据说话比讲趋势管用,后面新业务上线周期也短了,迭代快,半年接了三个新业务都没加集群。
我们后来还把向量检索的耗时埋点接进统一监控,慢查询一眼能定位到是哪个索引在拖,调优不再靠猜,DBA 也敢动参数了。新业务接入时我们也强制走这套轻量方案,避免有人图省事又去申请向量集群,技术栈才守得住,维护成本一直压在低位是真金白银。
热点模型预热我们也接了自动调度,访问曲线一上来系统自己就把对应模型 load 好,不用人工盯,稳态延迟一直压得很低,运维也省心。
第一个坑是索引参数。pgvector 的 ivfflat 要设 Lists,我们一开始按文档默认值设得偏小,召回率掉得狠,Top5 命中率只有六成多。后来按数据量把 Lists 调到合理区间,再配合理的 probes,召回率回到九成以上。
ivfflat 的 probes 我们试过从 10 调到 40,召回涨了但延迟也涨,最后取 20 是个平衡,查询量和质量都顾得到,不是越大越好。第二个坎是混合检索的融合,向量分和关键词分量纲不同,我们用了归一化再加权的办法,权重靠离线评测定。
ivfflat 参数我们写进了上线 checklist,新库默认按数据量算 Lists,不再靠拍脑袋,新人接手也不会再踩召回掉的深坑。踩过一次就够了,规范比经验牢,传承也稳。
迁到 pgvector 后,检索延迟 P99 在几百毫秒内,满足客服场景。召回率从 ivfflat 参数坑时的六成多回到约 92%,Top5 命中率和之前 Milvus 方案基本持平。运维成本几乎归零,因为不用再养一套向量集群,DBA 本来就管 Postgres。
热词缓存上线后,约三成高频问法根本不进向量检索,这部分延迟降到毫秒,用户体感最快的就是这块。整体一年下来省了一台向量集群的资源和一个人月的运维,DBA 也不用半夜盯向量节点,这事大家都轻松。
热词缓存我们按业务高峰预热,大促前把高频问法提前灌进去,峰值延迟稳得很,DBA 说这是性价比最高的一刀。不碰模型就能变快,谁都乐意做,资源也省下一截。
中小规模知识库别盲目上专用向量库,pgvector 共用业务库更省心,前提是量没到千万级。ivfflat 的 Lists 和 probes 一定要按数据量调,默认值多半偏小,召回会偷偷掉,这点我们交过学费。
向量检索选型别追新追重,量没到就选轻量方案,pgvector 共用业务库省一套集群,DBA 也熟,出问题有人管比新潮更重要。混合检索要做分数归一化再融合,不然向量和关键词各说各话,重排别贪多吃前几十条足够。
迁移完我们留了 Milvus 的对比报表给老板看,召回持平成本砍半,老板才信轻量方案不是凑合。技术选型用数据说话比讲趋势管用,预算也好批了,后面新业务直接套。
案例片段(已脱敏): 某客服知识库,文档约 40 万篇,向量维度 768。我们迁 pgvector 的配置片段:
CREATE INDEX ON docs USING ivfflat (emb vector_cosine_ops) WITH (lists = 2000); SET ivfflat.probes = 20; 混合: score = 0.7*normalize(vector_topk) + 0.3*normalize(bm25_topk) 重排: rerank(candidates[:50]) -> top5 热词缓存: redis, TTL 300s, 命中直接返回调参前 Lists=100 时 Top5 命中仅 63%,调到 2000 后回到 92%,DBA 说终于不用半夜盯向量节点。