向量数据库短板及解决方案

索引内存消耗问题

索引的选择对于向量召回的性能至关重要,Milvus 支持了 Annoy,Faiss,HNSW等多种不同的索引,大部分索引必须加载进内存.
用户可以根据对延迟、内存使用和召回率的需求进行选择。对于大数据量,内存不足的场景,提供磁盘索引解决方案:
  1. DiskANN
    • DiskANN 依赖高性能的磁盘索引,借助 NVMe 磁盘缓存全量数据,在内存中只存储了量化后的数据。
    • DiskANN 适用于对于查询 Recall 要求较高,QPS 不高的场景。

DiskANN 示意图
  • DiskANN 的关键参数:
    1. search_list: search_list 越大,recall 越高而性能越差。search_list 的大小不应该小于 K。而对于较小的 K,推荐把 search_list 和 K 的比值设置得相对大一些, 这个比值随着 K 增大可以逐渐靠近
    2. IVF_PQ
      • 对于精确度要求不高的场景或者性能要求极高的场景。
      • IVF PQ 的核心是两个算法,IVF + PQ 量化,其中量化可以大幅减少向量的占用内存量。
  • IVF 参数
    • nlist:一般建议 nlist = 4*sqrt(N),对于 Milvus 而言,一个 Segment 默认是 512M 数据,对于 128dim 向量而言,一个 segment 包含 100w 数据,因此最佳 nlist 在 1000 左右。
    • nprobe:nprobe 可以 Search 时调整搜索的数据量,nprobe 越大,recall 越高,但性能越差。具体的 nprobe 需要根据查询的精度要求决定,从 nprobe = 16 开始会是一个不错的尝试。
  • PQ 参数
    • M: 向量做 PQ 的分段数目,一般建议设置为向量维数的 1/4,M 取值越小内存占用越小,查询速度越快,精度也变得更加低。
    • Nbits: 每段量化器占用的 bit 数目,默认为 8,不建议调整。

大数据量性能瓶颈问题

解决方案:

分布式云原生部署方案, 数据分片分表分区,合理的预计数据量,表数目大小,QPS 参数等指标

在部署 Milvus 之前,首先需要决定机器的资源、规格、以及一些依赖的资源,以下是你需要考虑的因素:

  1. 有多少张表?

  2. 每张表的数据量有多少?

  3. 每张表的 QPS 需求有多少?

  4. 是否需要存标量字段,如果有字符串,字符串的平均长度是多少?

  5. 是否有删除和流式插入,每天大概有多少比例的数据需要被更新?

基于以上因素,可以遵循以下经验结论:

  1. 节点资源占用可以通过 sizing tool[2] 进行计算,通常情况下 8G 内存可以支持超过 5MB 的 128dim 向量数据和 1MB 的 768dim 数据。
  2. 默认情况下,Milvus 会创建 256 个消息队列 topic。如果表数目比较少,可以调整 rootCoord.dmlChannelNum 减少 topic 数目降低消息队列负载。
  3. 默认情况下,每个 collection 会使用 2 个消息队列 topic(shard),如果写入非常大或者数据量极大,需要调整 collection 的 shard 数目。建议每个 shard 写入 / 删除不超过 10M/s,单个 shard 的数据量不大于 1B 向量,shard 数目过大也会影响写入性能,因此不建议单表超过 8 个 shard。
  4. 根据 benchmark[3] 结果计算需要的 CPU 资源。对于小数据量场景(小于 5mn),使用多副本可以扩展查询性能,但建议副本数目不要超过 10 个。对于中大数据量场景,通常扩容 querynode 就可以自动负载均衡,不需要使用多副本提升 QPS.
  5. 所有的标量字段目前也会加载进内存中,也会消耗内存,请在容量规划时预留原始数据类型两倍以上的内存。
  6. Milvus 在存储数据的过程中,存在较多冗余数据(https://github.com/milvus-io/milvus/issues/20453)。考虑到 Minio 的 2,4 纠删码存在两副本冗余,我们建议 Minio 至少包含 6 倍以上的数据的磁盘存储。同时 Pulsar/Kafka 需要包含近五天写入量三倍的存储。合理调整数据的保留时间和 GC 时间可以很大程度上减少磁盘的使用,默认情况下数据会被保留 5 天。个人建议适当缩短数据过期时间,但尽可能保留 1 天以上避免数据丢失或误删除。
  7. Etcd 作为 Milvus 的元信息存储和服务发现节点,请尽可能使用 ssd 磁盘并独立部署。通常 Etcd 的内存使用不会超过 4GB,通过调整参数可以较快地清理 etcd 中的历史版本减少内存使用。
  8. Pulsar/Kafka 作为 Milvus 的日志存储,其依赖的 zookeeper 集群对性能要求也比较高,建议使用 SSD 并独立部署。

标量过滤性能如何保证

作为数据库,Milvus 支持了删除、标量过滤、TimeTravel 等高级特性。如果不了解底层原理,使用这些高级功能可能会对稳定性和性能造成比较严重的影响,以下是一些使用注意事项:

  1. Milvus 使用的是前过滤,即先做标量过滤生成 Bitset,在向量检索的过程中基于 Bitset 去除掉不满足条件的 entity。对于 HNSW 这一类的图索引而言,标量过滤并不会加速查询,反而可能导致性能变差。特别是对于过滤性很强的条件(比如 PK=1 这种全局唯一的条件),标量过滤甚至会导致单次查询的时间长于爆搜。针对这种情况,用户也可以选择通过后过滤的方式绕过,先基于 Milvus 查出 TopK 的数据,再基于其他数据库进行过滤。

  2. 对于过滤条件相对比较确定的场景,使用 Partition 把数据进行物理分区,在查询的时候指定 Partition 性能更好。

  3. Milvus 的删除是标记删除,在 compaction 时会清理,因此删除的数据依然会占据内存。大量删除也会造成查询性能下降,同时大量 compaction 可能造成建索引压力变大等一系列影响。在需要大量频繁删除的场景,可能需要进行一些 compaction 参数的调整,保证删除的数据能够被及时清理。

  4. Milvus 支持了数据自动过期功能(TTL),可以定时清理过期数据。

  5. 如果需要全量更新一个 Collection 的数据,推荐使用新建表 + 导入数据 + Alias 切换的方案。

  6. 制定 Output field 时,如果要获取标量字段,会从对象存储上获取,吞吐和延迟都会受到较大影响。

当然,Milvus 后续的版本会对以上能力做针对性的优化,尤其是删除和标量过滤的场景。

外部解决方案包括:

外挂CK、ES等分析引擎作为标量过滤组件

  • 15
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值