在 Azure AI 搜索中为大型数据集编制索引
如果需要在搜索解决方案中为大型或复杂数据集编制索引,本文将探讨在 Azure AI 搜索中应对长时间运行进程的策略。
这些策略假定你熟悉两种导入数据的基本方法:将数据推送到索引,或使用搜索索引器从支持的数据源拉取数据。 如果你的场景涉及计算密集型 AI 扩充,则需要使用索引器,因为索引器的技能依赖性很强。
本文补充了提高性能的提示,其中提供了有关索引和查询设计的最佳做法。 设计良好的索引(仅包含所需的字段和属性)是大规模索引编制的重要先决条件。
我们建议使用 2024 年 4 月 3 日之后创建的较新的搜索服务,以便为每个分区提供更高的存储。
注意
本文中所述的策略假定针对单个大型数据源。 如果解决方案需要从多个数据源编制索引,请参阅在 Azure AI 搜索中为多个数据源编制索引,了解建议的方法。
使用推送 API 为数据编制索引
推送 API(例如文档索引 REST API 或 IndexDocuments 方法 (Azure SDK for .NET))是 Azure AI 搜索中最常见的索引形式。 对于使用推送 API 的解决方案,长期运行的索引策略具有以下一个或两个组件:
- 批处理文档
- 管理线程
每个请求批处理多个文档
为大量数据编制索引的一种简单机制是在单个请求中提交多个文档或记录。 只要整个有效负载小于 16 MB,则请求就可以在一个批量上传操作中最多处理 1,000 个文档。 无论是在 .NET SDK 中使用文档索引 REST API 还是 IndexDocuments 方法,这些限制都适用。 不管使用什么 API,都可以在每个请求的正文中打包 1,000 个文档。
批处理文档可显著缩短处理大量数据所需的时间。 确定数据的最佳批大小是优化索引编制速度的关键。 影响最佳批大小的两个主要因素是:
- 索引的架构
- 数据的大小
因为最佳批大小取决于你的索引和数据,所以最好的方法是测试不同的批大小,以确定可为你的方案实现最快索引编制速度的批大小。 有关使用 .NET SDK 测试批大小的示例代码,请参阅教程:使用推送 API 优化索引编制。
管理线程和重试策略
索引器具有内置的线程管理,但在使用推送 API 时,应用程序代码需要管理线程。 请确保有足够的线程来充分利用可用的容量,尤其是在最近已增加分区或已升级到更高层搜索服务的情况下。
当你增加命中搜索服务的请求时,可能会遇到表示请求没有完全成功的 HTTP 状态代码。 在编制索引期间,有两个常见的 HTTP 状态代码:
503 服务不可用:此错误表示系统负载过重,当前无法处理请求。
207 多状态:此错误意味着某些文档成功,但至少一个文档失败。
为了处理故障,应使用指数退避充实策略来重试请求。
Azure .NET SDK 会自动重试 503s 和其他失败的请求,但要重试 207s,你需要实现自己的逻辑。 还可以使用 Polly 等开源工具来实现重试策略。
使用索引器和拉取 API
索引器具有多个功能,这些功能可用于长时间运行的进程:
- 批处理文档
- 对分区数据并行编制索引
- 安排计划和检测更改以便仅对新文档编制索引并随时为更改的文档编制索引
索引器计划可以继续上个已知停止点的处理。 如果数据未在处理时段内完全编制索引,则索引器在下次运行时会从中断的位置继续,前提是你使用的是提供更改检测的数据源。
将数据分区成较小的独立数据源可以实现并行处理。 可以拆分源数据,例如将其拆分到 Azure Blob 存储中的多个容器中,为每个分区创建数据源,然后根据搜索服务的搜索单位数并行运行索引器。
检查索引器批大小
与推送 API 一样,索引器允许配置每个批处理的项数。 对于基于创建索引器 REST API 的索引器,可以设置 batchSize
参数来自定义此设置,以便与数据特征更相符。
默认批大小特定于数据源。 Azure SQL 数据库和 Azure Cosmos DB 的默认批大小为 1,000。 相反,当平均文档大小较大时,Azure Blob 索引编制会将批大小设置为 10 个文档。
用于长时间运行的进程的计划索引器
索引器计划是用于处理大型数据集和调节缓慢运行进程(例如,扩充管道中的图像分析)的重要机制。
通常,索引器处理在 2 小时的时段内运行。 如果索引工作负载需要数天而不是数小时才能完成,则可以将索引器置于每两小时启动一次的连续定期计划中。 假设数据源已启用更改跟踪,索引器会在上次中断的位置继续处理。 按这种节奏,索引器可以处理很多天的文档积压工作,直到处理完所有未处理的文档。
{
"dataSourceName" : "hotels-ds",
"targetIndexName" : "hotels-idx",
"schedule" : { "interval" : "PT2H", "startTime" : "2024-01-01T00:00:00Z" }
}
当数据源中不再有任何新的或更新的文档时,索引器执行历史记录会报告已处理的 0/0
个文档,并且不会进行任何处理。
有关设置计划的详细信息,请参阅创建索引器 REST API 或为 Azure AI 搜索计划索引器。
注意
某些在较旧运行时体系结构上运行的索引器的最大处理时段为 24 小时,而不是 2 小时。 2 小时的限制适用于在内部托管的多租户环境中运行的较新内容处理器。 Azure AI 搜索会尽可能尝试将索引器和技能组处理卸载到多租户环境中。 如果无法迁移索引器,索引器会在专用环境中运行,并且可以运行长达 24 小时。 如果要计划表现出这些特征的索引器,请假定处理时段为 24 小时。
并行运行索引器
如果已对数据进行了分区,可以创建多个索引器数据源组合,从每个数据源拉取并写入同一搜索索引。 由于每个索引器都是不同的,可以同时运行它们,填充搜索索引的速度比按顺序运行它们更快。
请确保有足够的容量。 服务中的每个搜索单位在任何给定的时间都只能运行一个索引器。 只有当索引器可以并行运行时,创建多个索引器才有用。
对于基于文本和基于技能的索引,可以同时运行的索引作业数有所不同。 有关详细信息,请参阅索引器执行。
如果数据源是 Azure Blob 存储容器或 Azure Data Lake Storage Gen 2,则在完成此操作前,枚举大量 Blob 可能需要很长时间(甚至数小时)。 因此,索引器的成功文档计数似乎在此期间不会增加,而就算有所增加,它似乎也没有取得任何进展。 如果希望针对大量 Blob 的文档处理速度更快,可以考虑将数据分区到多个容器中,并创建指向单个索引的并行索引器。
登录 Azure 门户并检查搜索服务使用的搜索单位数。 选择“设置”>“缩放”,在页面顶部查看数量。 并行运行的索引器数约等于搜索单位数。
在多个容器之间进行源数据分区,或者对同一容器中的多个虚拟文件夹进行分区。
在每个索引器中指定同一目标搜索索引。
计划索引器。
查看索引器状态和执行历史记录以进行确认。
存在一些与并行索引相关的风险。 首先,回顾一下,索引不在后台运行,增加了查询被限制或删除的可能性。
其次,Azure AI 搜索不会锁定用于更新的索引。 并发写入是受管理的,如果特定写入在第一次尝试时不成功,则会调用重试,但你可能会注意到索引失败次数的增加。
虽然多个索引器数据源集能够以同一索引为目标,但要注意可以覆盖索引中现有值的索引器运行。 如果第二个索引器数据源以相同的文档和字段为目标,则会覆盖第一次运行中的任何值。 字段值将被完全替换;索引器无法将多次运行中的值合并为同一字段。
为 Spark 上的大数据编制索引
如果有大数据体系结构,并且数据位于 Spark 群集上,建议使用 SynapseML 加载数据并为其编制索引。 本教程包含调用 Azure AI 服务进行 AI 扩充的步骤,但你也可以使用 AzureSearchWriter API 进行文本索引编制。