矢量索引大小和保持在限制范围内

对于每个矢量字段,Azure AI 搜索使用字段上指定的算法参数构造内部矢量索引。 由于 Azure AI 搜索对矢量索引大小施加了配额,因此你应了解如何估算和监视矢量大小,以确保持在限制范围内。

注意

关于术语的说明。 在内部,搜索索引的物理数据结构包括原始内容(用于需要非标记化内容的检索模式)、倒排索引(用于可搜索文本字段)和矢量索引(用于可搜索的矢量字段)。 本文介绍支持每个矢量字段的物理矢量索引的限制。

提示

矢量量化和存储配置现在以预览版提供。 你可以使用窄数据类型,应用标量量化,并消除某些存储要求(如果不需要数据)。

有关配额和矢量索引大小的要点

  • 矢量索引大小以字节为单位。

  • 搜索索引级别没有配额。 矢量配额是在分区级别服务范围内强制实施的。 配额因服务层级(或 SKU)和服务创建日期而异,较新的服务每个分区的配额要高得多。

  • 矢量配额主要围绕内存约束进行设计。 所有可搜索的矢量索引都必须加载到内存中。 同时,还必须有足够的内存用于其他运行时操作。 存在矢量配额是为了确保整个系统对所有工作负载保持稳定和均衡。

  • 矢量配额以物理存储表示,物理存储取决于分区大小和数量。 每个层提供越来越强大且更大的分区。 更高的层和更多的分区使你能够使用更多的矢量配额。 在服务限制中,矢量配额上限基于所有矢量索引可以集体使用的物理空间量上限,假设所有分区都用于该服务。

    例如,在受支持的区域中的新服务上,某个基本搜索服务上所有矢量索引的总和不能超过 15 GB,因为基本层最多可以有三个分区(每个分区 5 GB 配额)。 在 S1 上,最多可以有 12 个分区,每个分区矢量数据的配额为 35 GB,如果分配所有 12 个分区,则上限为 160 GB。

如何检查分区大小和数量

如果不确定你的搜索服务的限制,可通过以下两种方法获取该信息:

  • 在 Azure 门户中的搜索服务“概览”页中,“属性”选项卡和“使用情况”选项卡显示了分区大小和存储,以及矢量配额和矢量索引大小。

  • 在 Azure 门户中的“缩放”页中,可以查看分区的数量和大小。

如何检查服务创建日期

与较旧的服务相比,在相同的层计费费率下,2024 年 4 月 3 日之后创建的较新的服务提供 5 到 10 倍的矢量存储。 如果你的服务较旧,请考虑创建新服务并迁移内容。

  1. 在 Azure 门户中,打开包含你的搜索服务的资源组。

  2. 在最左侧的窗格中的“设置”下,选择“部署”。

  3. 找到搜索服务部署。 如果有许多部署,请使用筛选器查找“搜索”。

  4. 选择部署。 如果有多个,请单击以查看它是否解析为搜索服务。

    筛选后的部署列表的屏幕截图。

  5. 展开部署详细信息。 应会看到“已创建”和创建日期。

    显示创建日期的部署详细信息的屏幕截图。

  6. 了解搜索服务的年龄后,请根据服务创建查看矢量配额限制:

如何获取矢量索引大小

请求矢量指标是数据平面操作。 可以使用 Azure 门户、REST API 或 Azure SDK 通过服务统计信息和单个索引在服务级别获取矢量使用情况。

可以在“概述”页的“使用情况”选项卡上找到使用情况信息。门户页面每隔几分钟会刷新一次,因此,如果最近更新了索引,请在检查结果之前稍等片刻。

以下屏幕截图显示了一个标准 1 (S1) 层,它配置了一个分区和一个副本。 矢量索引配额(以兆字节为单位)是指为每个矢量字段创建的内部矢量索引。 总的来说,索引会消耗近 460 兆字节的可用存储,但矢量索引组件只占用此搜索服务中使用的 460 兆字节中的 93 兆字节。

“概览”页的“使用情况”选项卡的屏幕截图,其中显示了针对配额的矢量索引消耗。

“使用情况”选项卡上的磁贴会跟踪搜索服务级别的矢量索引消耗。 如果增加或减少搜索服务容量,磁贴会相应地反映该更改。

影响矢量索引大小的因素

影响内部矢量索引大小的三个主要因素:

  • 数据的原始大小
  • 所选算法的开销
  • 删除或更新索引中的文档所产生的开销

数据的原始大小

每个矢量通常是单精度浮点数的数组,位于类型为 Collection(Edm.Single) 的字段中。

矢量数据结构需要存储,在以下计算公式中表示为数据的“原始大小”。 使用此原始大小来估算矢量字段的矢量索引大小要求。

一个矢量的存储大小由其维数决定。 将一个矢量的大小乘以包含该矢量字段的文档数即可得出原始大小

raw size = (number of documents) * (dimensions of vector field) * (size of data type)

EDM 数据类型 数据类型的大小
Collection(Edm.Single) 4 个字节
Collection(Edm.Half) 2 个字节
Collection(Edm.Int16) 2 个字节
Collection(Edm.SByte) 1 个字节

所选算法中的内存开销

每个近似最近的邻域 (ANN) 算法都会在内存中生成额外的数据结构,以实现高效搜索。 这些结构会消耗额外的内存空间。

对于 HNSW 算法,内存开销范围为 1% 到 20%

对于较高维度,内存开销较低,因为矢量的原始大小会增加;而额外的数据结构保持固定大小,因为它们存储有关图形中的连接的信息。 因此,额外数据结构造成的开销仅占总体大小的一小部分。

HNSW 参数 m 的值越大,内存开销就越高,该参数决定了索引构造期间为每个新矢量创建的双向链接数量。 这是因为,m 造成的开销大约为每个文档 8 到 10 个字节乘以 m

下表汇总了在内部测试中观察到的开销百分比:

维度 HNSW 参数 (m) 开销百分比
96 4 20%
200 4 8%
768 4 2%
1536 4 1%

这些结果展示了 HNSW 算法的维度、HNSW 参数 m 和内存开销之间的关系。

删除或更新索引中的文档所产生的开销

删除或更新包含矢量字段的文档时(更新在内部表示为删除和插入操作),基础文档将被标记为已删除,并在后续查询期间被跳过。 随着新文档编制索引并且内部矢量索引不断增长,系统会清理这些已删除的文档并回收资源。 这意味着,在删除文档之后,释放基础资源之前,可能存在一段滞后时间。

我们将此称为“已删除的文档比率”。 由于已删除的文档比率取决于服务的索引编制特征,因此没有通用的启发式方法来估算此参数,并且没有任何 API 或脚本可以返回服务的实际比率。 我们已观察到,有一半客户的文档删除比率低于 10%。 如果你倾向于执行高频率的删除或更新,则可能会观察到较高的已删除文档比率。

这是影响矢量索引大小的另一个因素。 遗憾的是,没有任何一种机制可以显示当前的已删除文档比率。

估算内存中数据的总大小

考虑到前面描述的因素,若要估计矢量索引的总大小,请使用以下计算方法:

(raw_size) * (1 + algorithm_overhead (in percent)) * (1 + deleted_docs_ratio (in percent))

例如,为了计算 raw_size,让我们假设你使用的是一个流行的 Azure OpenAI 模型,即具有 1,536 个维度的 text-embedding-ada-002。 这意味着一个文档将消耗 1,536 个 Edm.Single(浮点数),即 6,144 个字节,因为每个 Edm.Single 为 4 个字节。 包含单个 1,536 维矢量字段的 1,000 个文档总共将消耗 1000 个文档 x 1536 个浮点数/文档 = 1,536,000 个浮点数,或 6,144,000 个字节。

如果有多个矢量字段,则需要对索引中的每个矢量字段执行此计算,并将所有计算结果相加。 例如,包含两个 1,536 维矢量字段的 1,000 个文档将消耗 1000 个文档 x 2 个字段 x 1536 个浮点/文档 x 4 字节/浮点 = 12,288,000 字节。

若要获取矢量索引大小,请将此 raw_size 乘以算法开销已删除文档比率。 如果所选 HNSW 参数的算法开销为 10%,而已删除的文档比率为 10%,则会得到:6.144 MB * (1 + 0.10) * (1 + 0.10) = 7.434 MB

矢量字段如何影响磁盘存储

矢量数据的磁盘存储开销大约是矢量索引大小的三倍。

存储与矢量索引大小配额

服务存储和矢量索引大小配额不是独立的配额。 矢量索引会作为一个整体来影响搜索服务的存储配额。 例如,如果你的存储配额已耗尽,但还有剩余的矢量配额,则无法对任何其他文档编制索引,无论它们是否是矢量文档,除非你扩展分区以提高存储配额,或删除文档(文本或矢量文档)以减少存储使用量。 同样,如果矢量配额已耗尽,但还有剩余的存储配额,则进一步尝试索引编制将会失败,除非通过删除某些矢量文档或扩展分区来释放矢量配额。