本页介绍了MongoDB Vector Search 的关键性能优化策略,以及我们如何使用这些策略来创建基准测试。要学习;了解如何解读本指南,请参阅 如何使用此基准。
在基准测试中,我们使用了 Amazon Reviews 2023 数据集,这是一个包含 571.54M 条评论的庞大电子商务数据集,涵盖 33 个产品类别,代表从 1996 年 5 月到 2023 年 9 月的交互记录。这些评论涵盖了约48.2 百万件独特的商品,提供了丰富的多模态数据,包括用户评论(分数、文本、有用性投票)、商品元数据(描述、价格、图片)以及用户与商品交互图表。我们查看了商品数据集的子集(5.5M)以及 15.3M) 包含标题和说明,并使用 Voyage AI 的 voyage-3-large
模型根据以下逻辑将其嵌入:
source = "Item: Title: " + record["title"] + " Description: " + record["description"] source_embedding = vo.embed(source, model="voyage-3-large", input_type="document", output_dimension=2048)
过滤器的结果质量通过计算 Jaccard 相似度(intersection / expected number of results
)来确定,该相似度基于 ANN 查询结果与对应文本输入及请求向量数量的浮点 ENN 结果对比得出。召回率是通过计算 50 个可能被用于电子商务数据集的示例查询的平均交集来得出的。
注意
要查看用于基准测试的源代码以及用于嵌入源数据集的代码,请参阅性能测试存储库。
影响性能的因素
本节概述了影响MongoDB Vector Search 性能的几个因素,以及我们如何配置基准测试来测试这些因素。
量化
量化通过降低向量嵌入的精度来减少内存使用并提高搜索速度,但会以牺牲搜索准确性为代价。
标量量化
标量量化将 32 位浮点向量转换为 8 位整数,实现内存使用量减少 4 倍。与浮点向量相比,整数向量的比较所需的计算时间更少,所需资源也更少,但可能会导致搜索精度的下降。
二进制量化
二进制量化将向量转换为 1 位表示形式,实现内存使用量减少 32 倍。二进制向量比较涉及计算汉明距离,与 int 向量相比,计算时间甚至更短,资源消耗更少。然而,从浮点向量到二进制向量的转换会导致搜索精度显著下降,为了弥补这一损失,我们添加了一个重新评分步骤,这会增加延迟。在查询时,搜索过程中累积的前 numCandidates
个结果会根据其在磁盘上的完整保真度向量进行重新排序,然后再输出前 limit
个结果。
向量维度
我们使用 Voyage AI 的 voyage-3-large
模型嵌入了中型 (5.5 M) 和大型 (15.3 M)向量数据集。我们选择这种嵌入模型,是因为它在许多 IR 基准测试中表现出色,并且因为它在训练时同时考虑了套娃表征学习和量化。因此,该模型在启用量化的情况下,即使在处理高容量向量时,也能在低维度场景中保持优异性能。
我们利用视图索引生成附加字段,这些字段对源 2048 维向量的前 N 维进行切分,生成 1024、 512 和 256 维向量,并像对源字段一样对它们进行索引。
注意
您必须使用 MongoDB 版本 8.1 或更高版本才能在视图上创建向量搜索索引。
db.createView( "all_dims_amazon_dataset", "2048d_amazon_dataset", [ { $addFields: { "1024_embedding": { $slice: ["$embedding", 1024] }, "512_embedding": { $slice: ["$embedding", 512] }, "256_embedding": { $slice: ["$embedding", 256] } } } ] )
db.all_dims_amazon_dataset.createSearchIndex( "all_dims_vector_index", "vectorSearch", { "fields": [ { "numDimensions": 2048, "path": "embedding", // original 2048d embedding produced by voyage-3-large "quantization": "scalar", // adjust to binary when needed "similarity": "dotProduct", "type": "vector" }, { "numDimensions": 1024, "path": "1024_embedding", "quantization": "scalar", "similarity": "cosine", // sliced embeddings aren't normalized, so must use cosine "type": "vector" }, { "numDimensions": 512, "path": "512_embedding", "quantization": "scalar", "similarity": "cosine", "type": "vector" }, { "numDimensions": 256, "path": "256_embedding", "quantization": "scalar", "similarity": "cosine", "type": "vector" } ] } )
与每个位置的不同表征类似,不同的维度也会影响每个向量的表征能力。因此,与 256 维向量相比,使用 2048 维向量可以实现更高的准确性,尤其是在与 2048 维浮点数 ENN 基线进行比较时。
除了需要更多的存储和内存之外,与低维向量相比,查询高维向量的速度也慢一些,但由于MongoDB Vector Search 在执行向量比较时会利用SIMD指令,因此这一问题得到显着缓解。
过滤
我们还在包含所有 15.3M 项的集合上创建了一个单独的索引定义,其中包括两个字段的过滤器,以便对该数据集进行预过滤查询。
db.large_amazon_dataset.createSearchIndex( "vectorSearch", "large_vector_index", { "fields": [ { "numDimensions": 2048, "path": "embedding", "quantization": "scalar", // adjust to binary when needed "similarity": "dotProduct", "type": "vector" }, { "path": "category", "type": "filter" }, { "path": "price", "type": "filter" } ] } )
我们针对大型索引数据集运行未过滤和已过滤的向量搜索查询:
# unfiltered query query = [ { "$vectorSearch": { "index": "large_vector_index", "path": "embedding", "queryVector": embedding.tolist(), "limit": k, "numCandidates": candidates, } }, { "$project": {"embedding": 0} } ]
# filtered query query = [ { "$vectorSearch": { "index": "large_vector_index", "path": "embedding", "queryVector": embedding.tolist(), "limit": k, "numCandidates": candidates, "filter": {"$and": [{'price': {'$lte': 1000}}, {'category': {'$eq': "Pet Supplies"}}]} } }, { "$project": {"embedding": 0} } ]
注意
两种查询模式均通过使用 $project
阶段排除输出中的嵌入字段。除非需要在结果中嵌入内容,否则建议使用此方法来减少延迟。
搜索节点配置
MongoDB Vector Search 性能通过专用搜索节点扩展,这些节点独立于主节点 (primary node in the replica set)数据库工作负载处理向量计算,并高效利用专用硬件实例。所有测试均使用 M20
基本集群进行,但根据测试类型,我们重新配置了搜索节点,以更好地适应我们的测试用例。所有测试均使用Amazon Web Services us-east-1 上的搜索节点运行,us-east-1
中也有一个 EC2实例发出请求。您可以在Amazon Web Services上预配三种类型的搜索节点,这三种类型在可用的磁盘、 RAM和 vCPU 方面各不相同:
节点类型 | 资源配置文件 | 推荐用法 |
---|---|---|
低 CPU | 低磁盘与内存比率(~6:1),低 vCPU | 对于许多未利用量化技术的工作负载,这是一个很好的起点 |
高 CPU | 高磁盘与内存比率(~25:1),高 vCPU | 高 QPS 工作负载或利用量化的工作负载的高效选择 |
存储优化型 | 高磁盘与内存比率(~25:1),低 vCPU | 利用量化技术的工作负载的成本效益选择 |
Amazon 数据集大小
768 维度的浮点向量会占用约 3kb 的磁盘空间。此资源要求与向量数量和每个向量的维数成线性比例:1M 768d 个向量占用 ~3 GB; 1M 1536d 占用约 6 GB。
通过量化,我们从存储在磁盘上的全保真向量生成表示向量,并将其保存在内存中。这会将标量量化所需的内存量减少 3.75 倍,将二进制量化所需的内存量减少 24 倍,但增加了存储未量化和量化向量所需的磁盘空间。
1 标量量化 768 维向量需要 0.8kb 的内存 (3/3.75
) 和约 3.8kb 的磁盘 (3 + 3/3.75
)。考虑到这些硬件选项和量化所需的资源,我们为不同的测试案例选择了以下搜索节点层级:
测试用例 | 所需资源(RAM,存储) | Search Node Tier RAM, disk, vCPUs | 2 个节点的价格 |
---|---|---|---|
中等数据集 (5.5M 向量(所有维度),标量量化 | 22, 104.5 GB | S50-storage-optimized 32 GB,843 GB,4 vCPUs | $1.04/hr |
中等数据集 (5.5M 向量(所有维度),二进制量化 | 3.43, 104.5 GB | S30-high-cpu 8 GB 213 GB 4 vCPUs | $0.24/hr |
大型数据集 (15.3M 向量,2048d),标量量化 | 32.64, 155.04 GB | S50-storage-optimized 32 GB,843 GB,4 vCPUs | $1.04/hr |
大型数据集 (15.3M 向量,2048 维),二进制量化 | 5.1, 155.04 GB | S30-high-cpu 8 GB 213 GB 4 vCPUs | $0.24/hr |
binData
向量压缩
对于大型数据集,我们利用了一项额外功能向量压缩,该功能可将源集合中每个向量的占用空间减少约 60%。当 ID 在源集合中解析时,这将加速查询中的步骤,这也是所有大型工作负载的推荐步骤。
并发
我们不仅评估了串行查询延迟,还评估了在同时发出 10 和 100 请求时的总吞吐量/QPS。
注意
处理更高吞吐量的推荐机制是水平扩展搜索节点的数量,我们在这些测试中没有测量。
分片
我们评估了对集群和集合进行分片对 _id
字段的系统吞吐量的影响,重点关注大型二进制量化索引的 10 和 100 请求并发性。