最近在做一个电商图片相似搜索的项目,数据量大概1.2亿条,用的Milvus 2.3,IVF_FLAT索引。建索引参数试了好几种,比如nlist从4096调到16384,nprobe也试过64、128,但召回率死活卡在85%左右。我确认过向量质量没问题(用的ImageBind提取的特征),也用欧式距离试过,效果差不多。现在产品要求至少95%的召回,不然用户搜出来的结果太偏。有没有大佬踩过类似的坑?是索引参数没调对,还是数据分布的问题?或者是不是该换HNSW?求指点,感谢!
用Milvus做亿级向量检索,召回率一直上不去怎么办?
全部回复
共 183 条IVF_FLAT在亿级数据上召回率卡85%挺常见的,nprobe调高收益会递减,而且检索延迟涨得厉害。你试试换成HNSW,M设32到48,efConstruction拉到500以上,efSearch给256左右,召回一般能到95%以上,就是内存占用会大不少。另外得确认下那1.2亿条里有没有大量重复或高度相似的图片,数据分布太集中也会拖累召回。还有个小点,ImageBind特征记得做归一化,不然欧式距离和内积结果会差挺多。
IVF_FLAT在亿级数据上召回率卡85%其实挺常见的,nprobe调到128之后收益就开始递减了,再往上加查询延迟吃不消。你这个量级nlist设16384其实有点偏小,每个簇里塞了七八千条向量,搜索时扫的簇内候选不够精细,召回自然上不去。可以试试把nlist拉到65536甚至更高,同时nprobe跟着提到256左右看看曲线拐点在哪。不过说实话,IVF系列本身就是用召回换速度的,想稳定到95%以上,HNSW确实更靠谱,就是内存占用会翻好几倍,1.2亿条得先算算机器扛不扛得住。另外你可以检查下ImageBind出来的向量有没有做归一化,如果用的是内积但向量没归一,跟欧式距离的结果会对不上,这个坑我踩过。还有个容易被忽略的点,Milvus里segment没compact之前,小segment太多也会拖累召回,可以先手动compact一遍再测。如果产品对延迟不是特别苛刻,HNSW配ef设200左右,95%召回基本没啥问题。
IVF_FLAT在亿级数据上召回率卡在85%其实挺常见的,尤其你这种图片相似搜索场景,数据分布往往不均匀,聚类中心容易扎堆在某些区域。nlist调到16384之后每个桶里的样本还是很多,nprobe开到128也未必能覆盖到真正近邻所在的那些桶。你可以先看看每个桶的样本量分布,如果方差特别大,那八成是聚类本身的问题。另外欧式距离和内积在你的特征上表现差不多,说明特征可能没做归一化,ImageBind出来的向量最好先L2 normalize一下再入库,不然距离度量会被模长带偏。至于换HNSW,召回确实能上去,但1.2亿条的内存开销你得先算算,图索引吃内存很凶,单机可能扛不住。我建议先别急着换索引,试试把nprobe继续往上拉到256甚至512看看召回曲线拐点在哪,同时检查一下是不是有大量向量本身就在边界上导致漏召。如果实在要95%以上,可以考虑IVF加PQ做粗排再用原始向量精排的两阶段方案,这样召回和延迟都能兼顾。