向量数据库Milvus数据库踩坑
背景
公司推荐业务想增加一路向量召回, 目前数据库选型Milvus。
Milvus的配置信息:
- Milvus 1.1.1版本
- 采用集群方式, 数据通过nfs共享
业务使用方式为: 传一组ID进来:
- 先调用MIlvus的
GetEntityByID
接口获取向量列表 - 根据获取到的向量ID调用Milvus的
Search
接口获取召回向量列表
线上进行压测后, 发现步骤1(GetEntityByID)耗时巨大, 在400ms+, 查询接口在30ms左右, 断定GetEntityByID必然存在问题。
定位原因
首先翻阅的官方文档issue, 但是说其已经优化过该接口, 性能已经很好了(https://github.com/milvus-io/milvus/issues/4756), 但现实情况是,该接口确实很慢, 存疑。
翻阅代码(源码地址: DBImpl—-> GetVectorsByIdHelper方法), 查看GetEntityByID
背后的具体原理, 其执行步骤有以下:
- 遍历待查询的segement文件
- 从程序缓存中读取文件对应的bloom块, 命名为bloom_from_cache
- 判断ID是否在bloom块中
- 从程序缓存中读取文件对应的 ID文件块, 命名为uid_from_cache
- 从ID文件块中判断该ID的偏移量offset
- 根据偏移量,加载指定向量LoadsSingleVector
这里重点看了下从缓存读取值的情况, 发现uid_from_cache, 未读到, 会文件, 但查完文件后, 并没有把数据重写到缓存中
1 |
|
加上日志打印, 重新编译源码, 验证发现每次都是查文件, 并没有读缓存。但是读nfs文件,是比较费时的网络IO操作
所以这里我们大致判断为读文件问题。
然后我们线上进行对比压测, 将数据从nfs存储调整为硬盘存储。 重新压测, 发现响应时间确实降低很多。
然后去官方微信群里询问问题
1 |
|
官方答复:
1 |
|
最终解决方案
问题基本明了, 是为了保证索引性能, 才对get_entity_by_id 有性能牺牲。 且官方建议, 采用其他方式比如Mysql, redis,Mongo缓存 ID和向量的映射。避免在高并发下调用get_entity_by_id, 因为该接口读取文件性能不佳。
所以我们最终采用Redis缓存 ID和向量关系