最近在做一个图片查重的小项目,用的Milvus 2.3,索引类型是IVF_FLAT,nlist设了1024,数据量大概50万条128维向量。单机部署,16核32G内存,本地测试单条查询延迟还行,但上线后并发一高(大概200QPS),CPU直接飙到90%,响应时间从20ms涨到200ms+。自己试了调大nprobe、换HNSW索引,效果不明显。想问下各位大佬,这种场景是硬件瓶颈还是参数没调好?有没有必要上GPU或者换分布式方案?另外,业务上允许一点精度损失,像PQ量化这种是不是能换来性能提升?希望有实战经验的朋友指点一下,谢谢!
用向量数据库做相似图片检索,QPS上不去怎么优化?
全部回复
共 146 条PQ量化加SSD换内存,你这配置瓶颈在CPU而非索引,先试下MMap和查询并发控制。
PQ量化肯定得试,50万向量这规模上GPU太浪费,先把nprobe调到64看看。
50万向量真不算大,你这配置瓶颈大概率在CPU和内存带宽上,IVF_FLAT对128维暴力算距离,200QPS扛不住正常。PQ量化值得试,精度损失换3-5倍性能提升很划算,nprobe调小点比如64,召回率应该还能接受。另外建议看看是不是没用上多线程,Milvus的search请求线程数调满,再配合batch查询接口,QPS翻倍不难。别急着上GPU,先把CPU和索引调优做完再说。
说实话你这个配置和参数,瓶颈大概率不在硬件本身,16核跑IVF_FLAT的50万向量不该这么拉胯。我怀疑你nprobe调的方向可能反了,并发高的时候nprobe从8往16、32加,召回是上去了但CPU全耗在粗排距离计算上,200QPS直接吃满很正常。建议先试试把nlist降到512甚至256,同时nprobe固定到4左右,这样每条查询的扫描量能砍掉一大截,延迟和CPU都能降下来。PQ量化确实值得上,你允许精度损失的话,把128维切成16段、每段8bit,内存直接缩到原来的1/8,CPU缓存命中率会大幅提升,QPS翻倍不是问题,而且IVF_PQ在Milvus里支持得挺成熟。另外注意一下你的查询向量有没有做归一化,没归一化的话内积计算会额外消耗不少CPU周期,这个细节很多人忽略。如果改完还是撑不住,再考虑加一台机器做分片,别急着上GPU,你这数据量GPU的吞吐优势发挥不出来,反而增加运维复杂度。最后提醒下,检查下Milvus的线程池和连接数配置,默认值经常不够用,连接排队可能比检索本身更拖后腿。
50万条128维真不算大,你这配置单机跑200QPS按理说不该这么拉胯,先查下召回率和CPU热点是不是卡在距离计算上。IVF_FLAT加nprobe调大确实会放大计算量,既然允许精度损失,直接上PQ或者IVF_PQ,量化后内存占用和耗时都能降一大截。另外Milvus的配置文件里也有不少可以抠的,像query的并发线程数、gpu资源池分配,16核机器别让默认参数把资源吃满。真要还不行,可以试试把数据拆成两个分片做负载均衡,但分布式对你这数据量有点小题大做,大概率还是参数和索引选型的问题。
说实话你这个问题大概率不是硬件瓶颈,16核32G跑50万向量不应该这么拉胯。IVF_FLAT在高并发下主要卡在磁盘IO和CPU的暴力计算上,建议先试下把nlist降到512甚至256,同时把nprobe控制在32以内,光这两个参数就能省不少资源。PQ量化绝对值得试,你这业务允许精度损失,直接上IVF_PQ,内存占用能降8倍,QPS翻个3-4倍不是问题。另外Milvus的配置文件里有个cpu_cache_capacity可以调,给查询多分点内存,效果可能比换索引立竿见影。真要上GPU的话,你这数据量我觉得没必要,先把参数和量化玩明白了再说。
你这配置跑50万向量,IVF_FLAT在200QPS下CPU爆掉挺正常的,瓶颈大概率不在nprobe或索引类型,而是单机CPU的向量距离计算太吃资源。PQ量化确实值得试,精度损失不大的话能把内存占用和计算量降好几个档次,但记得先验证下召回率能不能接受。另外Milvus 2.3的查询走的是CPU并行,16核面对高并发确实吃力,如果预算允许,上GPU或换2.4版本的Milvus(支持GPU索引)会立竿见影,不然就得靠加副本横向扩展了。我这边之前类似场景是先用PQ把单条查询压到5ms内,再配合限流才稳住QPS,你可以参考下。
这配置抗200QPS确实勉强,先砍一半nprobe试试,PQ量化对查重场景收益挺大的。
50万向量真不大,瓶颈八成在CPU和内存带宽,换HNSW记得调ef参数,别只改索引类型。
PQ量化值得试,精度损失换3-5倍QPS提升很划算,另外记得把nprobe调到64左右配合CPU核数。
50万向量真不算大,你这配置单机跑200QPS按理说不该这么拉胯,先查查是不是查询线程池和连接数没调,Milvus默认配置经常在这块卡脖子。IVF_FLAT的nprobe调太大反而会让CPU做无用功,试试固定nprobe在64左右,然后把indexing的CPU资源让给查询。PQ量化确实值得试,你这场景允许精度损失的话,IVF_PQ能把内存占用砍掉一大截,延迟直接降一个量级,但记得先验证下召回率能不能接受。至于GPU和分布式,现阶段真没必要,先把单机压榨干净再说。
你这配置单条20ms其实挺正常了,50万向量上200QPS对CPU压力确实大,IVF_FLAT本质还是暴力扫描候选集。PQ量化建议试试,IVF_PQ能把内存占用降好几倍,配合nprobe调到32左右,延迟能压到50ms内,精度损失对图片查重这种场景基本无感。不过Milvus 2.3单机版并发上限就在那,真想稳上200QPS估计得上集群或者换知维的索引,另外试试把数据全塞内存里,别走磁盘。
你这配置跑50万向量200QPS确实到瓶颈了,IVF_FLAT本质是暴力扫描候选集,CPU带宽扛不住并发。建议先试PQ+IVF,量化后内存占用直接降4倍,128维压到32维,延迟应该能砍半。nprobe别调太大,8到16就够,精度损失换QPS很划算。另外Milvus的磁盘索引可以换mmap模式,内存不够时能缓解压力,但别指望质变。真要上2000QPS再考虑GPU或分布式,现在这规模上分布式反而网络开销拖后腿。
说实话50万向量这规模真不算大,16核32G跑200QPS上不去多半不是硬件瓶颈,IVF_FLAT在高并发下CPU都耗在遍历倒排索引上了。建议先把nprobe调小到16左右,再配合PQ量化把向量压缩到32维,延迟能降一大截。另外Milvus这边可以试试把mmap打开,把索引映射到内存外,能省不少CPU。
这配置扛200QPS确实有点勉强,16核跑IVF_FLAT基本都在吃CPU算距离。建议先试试把nprobe调到32-64,配合PQ量化(比如PQ64)能把内存占用降下来,QPS应该能翻倍。另外Milvus有个跟业务无关的优化——开内存映射和设置sealed搜索的并发线程数,我之前调完查询延迟稳了不少。要是还不行,可以先上GPU试水,单卡3090撑500QPS问题不大,分布式反而有点重了。
之前做个类似的项目,50万向量这个量级IVF_FLAT确实有点尴尬,nprobe调大反而放大CPU瓶颈。建议先试试把nlist降到512,同时开Milvus的mmap,内存占用能下来不少。PQ量化值得上,4位或者8位编码对精度影响很小,QPS能翻倍,你这场景查重完全够用。另外200QPS真不用上分布式,单机把资源吃满再说,实在不行就加个缓存扛热点。
50万向量真不算大,你这配置单机跑200QPS卡成这样,大概率不是硬件瓶颈。IVF_FLAT本质还是暴力扫描,nprobe调大只会更慢,建议直接上PQ或OPQ量化,精度损失换3-5倍性能很划算。另外检查下Milvus的search用的线程数是不是默认值,按16核调一下能明显改善并发。HNSW在这个数据量下构建内存占用太高,反而容易触发GC问题,不太推荐。真要上GPU的话,记得用IVF_PQ搭配GPU索引,但你这数据量其实没必要,先试试量化+调参吧。
之前做类似项目踩过同样的坑,IVF_FLAT在高并发下CPU都耗在距离计算上了,PQ量化确实值得试,之前我们用PQ把内存占用降了4倍,QPS翻了快3倍,精度损失在查重场景完全能接受。另外你这配置单机扛200QPS确实有点吃力,可以先试试把nlist调小到512,配合PQ看看,再不行就得考虑上GPU了,Milvus的GPU索引在并发上提升很明显。还有个细节,你查重的话可以加个布隆过滤器先筛一遍,能挡掉不少无效查询。
50万向量真不算大,你这配置瓶颈主要在CPU和内存带宽,先试试PQ量化把内存占用降下来,QPS能翻倍。
我们之前也踩过类似的坑,IVF_FLAT在50万量级下nlist=1024其实是偏大的,查询时候选集太大反而拖慢速度,建议先压到512试试,同时nprobe从16往下调,用召回率换QPS。另外你这配置瓶颈大概率在CPU的knn计算上,PQ量化确实值得试,把128维压到32维左右,延迟能降一个量级,精度损失在图片查重场景完全能接受。GPU就别想了,你这数据量上GPU纯属浪费,先把索引参数和量化搞定,200QPS单机应该能做到。
你这配置50万向量用IVF_FLAT确实有点尴尬,nprobe调大反而会让CPU更吃紧。建议先试试把nlist降到512或者256,同时把查询时的nprobe控制在8-16,配合PQ量化能明显降内存带宽占用。另外200QPS对16核来说算正常压力,想不换硬件的话可以加个缓存层,把热门图片的检索结果直接放Redis。不过说实话,这数据量真没必要上分布式,单机升到64G内存或者直接用HNSW加量化,效果会立竿见影。