扩展 Azure 流分析作业以增加吞吐量

本文介绍如何优化流分析查询,增加流分析作业的吞吐量。 可以使用以下指南来扩展作业,以便处理较高负载并充分利用更多的系统资源(如更多带宽、更多 CPU 资源、更多内存)。 作为先决条件,你可能需要阅读以下文章:

案例 1 – 在各个输入分区中,查询本质上是完全可并行的

如果在各个输入分区中,查询本质上是完全可并行的,则可以按照以下步骤操作:

  1. 通过使用 PARTITION BY 关键字来创作查询使之易并行。 请参阅此页易并行作业部分中的更多详细信息。
  2. 根据查询中使用的输出类型,某些输出可能是不可并行的,或者需要进一步配置来实现易并行。 请始终先合并输出,然后再将其发送到输出接收器。 Blob、表、ADLS、服务总线和 Azure Function 会自动并行化。 SQL 输出有一个用于并行化的选项。 事件中心需要将 PartitionKey 配置设置为与 PARTITION BY 字段(通常是 PartitionId)匹配。 对于事件中心,还要格外注意匹配所有输入和所有输出的分区数量,以避免分区之间的交叉。
  3. 使用 1 个 SU V2(即单个计算节点的全部容量)运行查询,来测量可实现的最大吞吐量;如果你使用的是 GROUP BY,则测量作业能处理的组数(基数)。 达到系统资源限制的作业,一般症状将如下所示。
    • SU 利用率指标超过 80%。 该指示内存使用率较高。 此处描述了导致此指标增加的因素。
    • 输出时间戳滞后于时钟时间。 根据查询逻辑,输出时间戳可能与时钟时间之间存在一个逻辑偏差。 但是,它们应该以大致相同的速度增进。 如果输出时间戳进一步滞后,则指示系统工作时间过长。 它可能是由于下游输出接收器限制,或高 CPU 利用率所致。 我们目前没有提供 CPU 利用率指标,因此很难区分两者。
      • 如果该问题是由接收器限制导致,则可能需要增加输出分区数(还要增加输入分区数,以使作业保持完全可并行化),或者增加接收器的资源量(例如,Cosmos DB 的请求单位数)。
    • 在作业关系图中,每个输出都有一个分区积压工作事件指标。 如果积压工作事件指标持续增加,则同样表示系统资源受到约束(由于输出接收器限制或高 CPU)。
  4. 在确定 1 SU V2 作业可达到的上限后,可在添加更多 SU 时线性推断出作业的处理容量,前提是你没有任何导致某些分区“紧迫”的数据倾斜。

注意

选择适当数量的流单元:由于流分析为所添加的每个 1 SU V2 都创建一个处理节点,因此最好将节点数作为输入分区数的除数,以便分区可均匀分布在各节点上。 例如,你已经测量出 1 SU V2 作业可实现 4 MB/秒的处理速率,并且输入分区计数为 4。 你可选择使用 2 个 SU V2 来运行作业来实现大约 8 MB/秒的处理速率,或者使用 4 SU V2 来实现 16 MB/秒的处理速率。 然后,你可以决定何时增加作业的 SU 数量以及增加至多少,以作为输入速率的一个函数。

案例 2 - 如果查询不易并行。

如果查询不易并行,可执行以下步骤。

  1. 首先使用不带 PARTITION BY 的查询来避免分区复杂性,然后使用 1 个 SU V2 运行查询来测量最大负载,如案例 1 中所示。
  2. 如果能在吞吐量方面达到预期负载,则目标达成。 或者,你可选择测量使用小数节点(2/3 个 SU V2 和 1/3 个 SU V2)运行的相同作业,找到适合你的场景的流单元最小数目。
  3. 如果无法实现所需的吞吐量,请尝试尽可能地将查询分解为多个步骤(如果尚没有多个步骤),并为查询中的每个步骤分配最多 1 个 SU V2。 例如,如果有 3 个步骤,则在“规模”选项中分配 3 个 SU V2。
  4. 在运行这类作业时,流分析会将每个步骤置于其自己包含专用 1 SU V2 资源的节点上。
  5. 如果仍未实现负载目标,可以尝试使用 PARTITION BY,从更接近输入的步骤开始。 对于不可自然分区的 GROUP BY 运算符,可以使用本地/全局聚合模式来执行分区的 GROUP BY,然后执行非分区 GROUP BY。 例如,如果你想要计算每 3 分钟通过每个收费站的车辆数量,并且数据量超出了 1 个 SU V2 可处理的量。

查询:

WITH Step1 AS (
SELECT COUNT(*) AS Count, TollBoothId, PartitionId
FROM Input1 Partition By PartitionId
GROUP BY TumblingWindow(minute, 3), TollBoothId, PartitionId
)
SELECT SUM(Count) AS Count, TollBoothId
FROM Step1
GROUP BY TumblingWindow(minute, 3), TollBoothId

在上述查询中,计算每个分区每个收费站的车辆数,然后将所有分区中的计数相加。

进行分区后,为步骤的每个分区分配 1 个 SU V2,这样每个分区都可置于其自己的处理节点上。

注意

如果无法对查询进行分区,则在多步骤查询中添加额外的 SU 可能无法始终有效地提高吞吐量。 获得性能的一种方法是,使用本地/全局聚合模式来减少初始步骤的数量,如前面的步骤 5 中所述。

案例 3 - 在作业中运行大量独立查询。

对于某些 ISV 用例,如果在单个作业中处理来自多个租户的数据更具经济效益,则可为每个租户使用单独的输入和输出,你可能最终会在单个作业中运行相当多的(例如 20 个)独立查询。 假设条件是每个此类子查询的负载都相对较小。 在这种情况下,可以按照以下步骤操作。

  1. 在这种情况下,请勿在查询中使用 PARTITION BY
  2. 如果使用事件中心,则将输入分区计数减少到可能的最低值 2。
  3. 使用 1 个 SU V2 运行查询。 通过每个子查询的预期负载,尽可能多地添加此类子查询,直到作业达到系统资源上限。 有关发生这种情况时的症状,请参阅案例 1
  4. 一旦达到上面测出的子查询上限,就可开始向新作业添加子查询。 作为独立查询数量的函数运行的作业数应是标准线性的,前提是你没有任何负载偏移。 然后,可根据你想要服务的租户数预测需要运行多少个 1 SU V2 作业。
  5. 将引用数据联接与此类查询结合使用时,应在使用相同引用数据进行联接之前将输入合并在一起。 然后再根据需要拆分事件。 否则,每个引用数据联接会在内存中保留一份引用数据,可能导致不必要的内存使用。

注意

每个作业中要放置多少租户? 此查询模式通常具有大量子查询,并导致非常大且复杂的拓扑。 作业控制器可能无法处理此类大型拓扑。 一般来说,1/3 SU V2 作业保持在 40 个租户以下,2/3 SU V2 作业和 1 SU V2 作业则为 60 个租户。 当超出控制器的容量时,作业将无法成功启动。

获取帮助

如需获取进一步的帮助,可前往 Azure 流分析的 Microsoft 问答页面

后续步骤