最近在做一个图片查重的小项目,用的Milvus 2.3,索引类型是IVF_FLAT,nlist设了1024,数据量大概50万条128维向量。单机部署,16核32G内存,本地测试单条查询延迟还行,但上线后并发一高(大概200QPS),CPU直接飙到90%,响应时间从20ms涨到200ms+。自己试了调大nprobe、换HNSW索引,效果不明显。想问下各位大佬,这种场景是硬件瓶颈还是参数没调好?有没有必要上GPU或者换分布式方案?另外,业务上允许一点精度损失,像PQ量化这种是不是能换来性能提升?希望有实战经验的朋友指点一下,谢谢!
用向量数据库做相似图片检索,QPS上不去怎么优化?
全部回复
共 154 条50万向量真不大,瓶颈八成在CPU和内存带宽,先试试PQ+IVF,200QPS应该能稳。
50万向量这个量级真不算大,你这配置单机跑200QPS理论上不该这么拉胯,先看看是不是没走批量查询接口,或者客户端连接池打满了。IVF_FLAT在这种并发下确实容易吃CPU,因为要扫的桶太多,你可以试试把nlist降到512甚至256,配合nprobe控制在8左右,召回率降一点但延迟会好看很多。PQ量化肯定是值得试的,128维压到32维,内存带宽和CPU开销直接降一个量级,我这边之前用IVF_PQ把类似场景的QPS从150提到400+,精度损失大概2%以内,业务基本无感。至于GPU或者分布式,我觉得真没必要,先查一下Milvus的配置是不是把mmap给关了,还有索引文件是不是全在内存里,这个数据量HNSW调好参数应该也能扛住。
50万条128维其实不算大,IVF_FLAT在200QPS下CPU打满,八成是nprobe给太高了,你可以先把nprobe压到16-32试试,召回掉一点但延迟会好很多。另外Milvus单机查询走的是CPU,HNSW建索引慢但查询更吃内存,你32G可能不太够它吃。PQ量化确实能换性能,50万这个量级用IVF_PQ或者SQ8都挺合适,精度损失一般业务能接受。真要上200QPS稳定跑,建议先看下是不是每次查询都带了标量过滤,那个才是隐形杀手。
50万条128维用IVF_FLAT,200QPS就CPU 90%其实挺正常的,IVF本身在并发下计算量就大。你可以先试试把nlist降到256或512,nprobe保持16左右,召回率损失不大但单次扫描的聚类数少了,CPU能降不少。另外50万数据量上HNSW确实更合适,但得把M和efConstruction调小点,不然内存和建索引时间都会炸。PQ量化能省内存但对CPU帮助有限,你这瓶颈更像是计算密集不是内存带宽,真要上量还是得分片或者走GPU版Milvus。
50万数据IVF_FLAT还200QPS就跪,先查查是不是没开mmap或者nprobe给太高了。PQ确实能救,但128维压太狠精度掉得厉害,可以试试IVF_PQ。
50万条128维的数据其实不算大,IVF_FLAT在200QPS下CPU飙到90%不太正常,你nprobe设的多少?如果nprobe设太高比如64以上,那基本等于暴力扫一大半聚类,CPU肯定扛不住。另外16核32G单机跑Milvus,milvus本身还有不少后台线程和segment合并开销,查询一密集资源抢得厉害。你换HNSW没效果我猜是没调efSearch,默认值可能偏大,HNSW在高并发下内存随机访问的模式反而更吃CPU cache,不一定比IVF省。PQ量化确实能换性能,50万条128维用PQ或者IVF_PQ,内存和计算量都能明显降,精度损失在查重场景一般能接受,但建议先用OPQ或者带残差的PQ。真正要提QPS,先确认瓶颈到底在向量检索还是在你前后处理,比如图片特征提取、网络IO这些,用Milvus的metrics或者perf工具看下各阶段耗时。如果确实是检索本身,可以考虑把nlist调大一点比如4096配合小nprobe,或者直接上GPU版Milvus,200QPS这个量级GPU基本轻松。分布式没必要,50万条单机足够,先压榨参数和硬件再说。
PQ量化确实能明显降内存和提吞吐,但50万数据量瓶颈多半在CPU,先试试开多线程查询或者降nlist。
50万条128维的数据量其实不算大,16核跑200QPS就飙到90%有点不正常,建议先看看是不是查询请求里带了其他过滤条件导致走了全量扫描。IVF_FLAT在这个量级下nprobe调到32左右应该就够了,调太大反而拖慢。你试过开mmap或者把向量加载方式改成内存映射吗?另外PQ量化确实能省内存和提速,但50万条用不着上PQ,收益有限还掉精度。真要说瓶颈,我怀疑是Milvus单机版的查询线程池配置或者CPU绑核没调好,可以看看配置文件里queryNode的并发参数。
50万条128维才200QPS就90%CPU有点怪,先看下是不是没开多线程或者每次查询都重建连接了。
200QPS就把16核打到90%,瓶颈大概率不在索引参数上,而是Milvus那条查询链路本身开销太重。IVF_FLAT每次都要扫原始向量算距离,nprobe调大只会更吃CPU,换HNSW也救不了并发。可以试试PQ或SQ8量化,50万条数据精度掉一点完全能接受,内存和算力都能省一大截。另外查一下是不是每次请求都带标量过滤或者走了全量扫描,这块经常是隐藏的坑。真要上量再考虑GPU版或者分片,单机这个配置其实还有不少榨的空间。
PQ量化确实能提性能,但50万数据量下建议先看看是不是Milvus的segment没合并,小文件太多也拖QPS。
200QPS单机跑IVF_FLAT确实有点吃力,CPU飙高大概率是nprobe开太大导致扫描的桶太多了,可以试着把nprobe压到16-32之间看看延迟能不能降下来,精度掉一点应该还能接受。50万条数据其实不算大,与其上GPU不如先试试HNSW加PQ量化,内存占用和计算量都能明显改善,IVF_FLAT在高并发下本身就不太占优势。另外查一下是不是每次查询都走了全量加载或者没开mmap,这些细节有时候比换硬件管用。
200QPS单机确实有点吃力,16核跑IVF_FLAT这个量级差不多就这样了。你试过开多副本+分片没?单机再调参数天花板有限,IVF本身内存占用和计算量都摆在那。PQ量化值得试,50万条128维压到16字节左右能省不少内存带宽,精度掉一点但召回一般还能接受。另外nprobe调太大反而拖慢,可以压到16-32配合重排看看。GPU这块看你预算,Milvus的GPU索引对QPS提升明显,但迁移成本得算一下。
50万条128维跑到200QPS就CPU 90%确实有点反常,先看看是不是每次查询都走了全量nprobe扫描,IVF_FLAT在nprobe偏高时基本等于暴力检索。你换HNSW没效果的话,检查下建索引时的M和efConstruction,还有查询时的ef参数,默认值往往偏保守。PQ量化肯定能降内存和加速,128维用SQ8或PQ分段量化精度损失可控,配合refine重排能找回来不少。另外200QPS单机16核本来就吃紧,Milvus的proxy和querynode分离部署会好一些,GPU倒不是必须的。