目录
索引
其他
存储优化
常见问题
索引
向量索引的基本概念请参考 向量索引概述。
选择合适的索引需要在存储空间、查询性能、查询召回率等多个指标中权衡。
- FLAT 索引
FLAT 是对向量的暴力搜索(brute-force search),速度最慢,但召回率最高(100%),磁盘空间占用最小。
随着目标向量数量增多,使用 CPU 做 FLAT 查询的耗时呈线形上升关系;而使用 GPU 查询时,批量查询的效率高,目标向量数量增加对查询耗时影响不大。
- IVF 系列索引
IVF 系列索引包括 IVF_FLAT、IVF_SQ8/IVF_SQ8H 和 IVF_PQ。IVF_SQ8/IVF_SQ8H 和 IVF_PQ 索引对向量数据做了有损压缩,磁盘占用量较少。
IVF 索引都有两个相同的参数:nlist 和 nprobe。nlist 是建索引参数,nprobe 是搜索参数。选取 nlist 和 nprobe 的推荐值,详见 性能优化问题 > 应如何设置 IVF 索引的nlist和nprobe参数?
根据相关原理,估算使用 IVF 索引进行查询时的计算量:
- 单个数据段计算量可估算为:目标向量数量 × (nlist + (段内向量数 ÷ nlist)× nprobe)
- 数据段的数量可估算为:集合数据总量 ÷ index_file_size
- 对集合查询所需的计算总量则为:单个数据段计算量 × 数据段数量
通过估算得出的计算总量越大,查询耗时越长。实际使用中可根据以上公式确定合理的参数,在满足召回率的前提下获得较高的查询性能。
在持续插入数据的场景下,由于对大小未达到 index_file_size 的数据段未建立索引,对其使用的查询方式是暴力搜索。计算量为:目标向量数量 x 该数据段向量总数。
- HNSW / RNSG / ANNOY 索引
HNSW、RNSG、ANNOY 的索引参数对查询性能的影响较为复杂,建议参考 索引概览。
其他
- 结果集
结果集的规模取决于目标向量数量和 topk。topk 的大小对计算的影响不大。但在目标向量数量和 topk 都较大的情况下,结果集序列化和网络传输的耗时会相应增加。
- MySQL
Milvus 使用 MySQL 作为元数据后端服务。Milvus 在查询数据时会多次访问 MySQL 以获取元数据信息,因此 MySQL 服务的响应速度对 Milvus 的查询性能有较大影响。
- 预加载
首次查询需要先将数据从磁盘读入缓存,因此耗时较长。为避免首次查询加载数据,可预先调用 load_collection 接口,或使用系统参数 preload_collection 指定启动 Milvus 时要预先加载的集合。
- 段数据整理
在 数据段整理 中提到,Milvus 在查询数据时将 delete_docs 读入内存以过滤被删除的实体。调用 compact 接口可清理被删除的实体,减少过滤操作,从而提高查询性能。
存储优化
- 数据段整理
在 数据段整理 中提到,被删除的实体不参与计算,并且占用磁盘空间。如果有大量的实体已被删除,你可以调用 compact 接口来释放磁盘空间。
常见问题
为什么查询时 GPU 一直空闲?
此时应该是在用 CPU 进行查询。如果要用 GPU 进行查询,需要在配置文件中将 gpu_search_threshold 的值设置为小于 nq (每次查询的向量条数) 。可以将 gpu_search_threshold 的值调整为期望开启 GPU 搜索的 nq 数。若 nq 小于该值,则用 CPU 查询,否则将使用 GPU 查询。不建议在查询批量较小时使用 GPU 搜索。
为什么搜索的速度非常慢?
请首先检查 server_config.yaml 的 cache.cache_size 参数是否大于集合中的数据量。
创建集合时 index_file_size 如何设置能达到性能最优?
使用客户端创建集合时有一个 index_file_size 参数,用来指定数据存储时单个文件的大小,其单位为 MB,默认值为 1024。当向量数据不断导入时,Milvus 会把数据增量式地合并成文件。当某个文件达到 index_file_size 所设置的值之后,这个文件就不再接受新的数据,Milvus 会把新的数据存成另外一个文件。这些都是原始向量数据文件,如果建立了索引,则每个原始文件会对应生成一个索引文件。Milvus 在进行搜索时,是依次对每个索引文件进行搜索。
根据我们的经验,当 index_file_size 从 1024 改为 2048 时,搜索性能会有 30% ~ 50% 左右的提升。但要注意如果该值设得过大,有可能导致大文件无法加载进显存(甚至内存)。比如显存只有 2 GB,该参数设为 3 GB,显存明显放不下。
如果向集合中导入数据的频率不高,建议将 index_file_size 的值设为 1024 MB 或者 2048 MB。如果后续会持续地向集合中导入增量数据,为了避免查询时未建立索引的数据文件过大,建议这种情况下将该值设置为 256 MB 或者 512 MB。
可参阅 如何设置 Milvus 客户端参数。
为什么同样的数据量,用 GPU 查询比 CPU 查询慢?
一般来说,当 nq(每次查询的向量条数)较小时,用 CPU 查询比较快。只有当 nq 较大(约大于 500)时,用 GPU 查询才会更有优势。
因为在 Milvus 中,每次用 GPU 查询都需要将数据从内存加载到显存。只有当 GPU 查询节省的计算时间能抵消掉数据加载的时间,才能体现出 GPU 查询的优势。
为什么有时候小的数据集查询时间反而更长?
如果数据文件的大小小于创建集合时 index_file_size 参数的值,Milvus 则不会为此数据文件构建索引。因此,小的数据集有可能查询时间会更长。你还可以调用 create_index 建立索引。