了解槽
BigQuery 槽是 BigQuery 用于执行 SQL 查询或其他作业类型的虚拟计算单元。在执行查询期间,BigQuery 会自动确定查询使用的 slot 数量。使用的槽数取决于处理的数据量、查询的复杂程度以及可用的槽数。通常,可用的槽越多,您可以运行的并发查询就越多,并且复杂查询可以运行得更快。
虽然所有查询都会使用槽,但您可以选择两种使用费结算方式:按需价格模式或基于容量的价格模式。
默认情况下,系统会采用按需模式向您收取费用。使用此模式时,您需要为每个查询处理的数据量(以 TiB 为单位)付费。采用按需价格模式的项目受每个项目和每个组织的槽限制,且具有瞬时突发功能。对于大多数采用按需模式的用户而言,槽容量限制绰绰有余。不过,根据工作负载的实际情况,可用的槽越多,查询性能也就越高。如需检查您的账号使用的槽数,请参阅 BigQuery 监控。
使用基于容量的价格模式,您需要为查询随时间推移而分配的槽容量付费。此模型可让您明确控制总槽容量,但按需价格模式无法做到。您可以通过预留明确选择要使用的槽数。您可以将预留中的槽数指定为始终分配的基准量,也可以指定为在需要时分配的自动扩缩量。
使用槽执行查询
BigQuery 在执行查询作业时,会将 SQL 语句转换为执行计划,此执行计划会分解为一系列查询阶段,而这些阶段本身是由多组更精细的执行步骤组成。BigQuery 会利用高度分布式的并行架构来运行这些查询,而这些阶段则会建立许多潜在工作器可能并行执行的工作单元模型。各阶段之间通过快速分布式 Shuffle 架构传递数据,Trusted Cloud by S3NS 博客详细介绍了该架构。
BigQuery 查询执行过程是动态的,也就是说,您可以在查询执行期间修改查询计划。在查询运行时引入的阶段通常用于改进所有查询工作器的数据分布。此外,随着其他查询完成或开始执行,或者自动扩缩器将槽添加到预留中,可用容量可能会发生变化,从而影响查询执行。
BigQuery 可以并发运行多个阶段,可以使用推测性执行技术来加速查询,并可动态地重新划分阶段以实现最佳并行性。
在查询的每个阶段,BigQuery 槽会执行个别工作单元。例如,如果 BigQuery 确定某一阶段的最佳并行化因子为 10,则它会请求 10 个槽以用于处理该阶段。
槽资源不足
如果查询请求的槽数超过可用槽数,BigQuery 会将个别工作单元排入队列,并等待槽变为可用状态。随着查询继续执行以及槽被释放,系统会动态地选取这些已排入队列的工作单元用于执行。
BigQuery 可以为查询的特定阶段请求任意数量的槽。所请求的槽数与您购买的容量无关,而是指示 BigQuery 为该阶段选择的最佳并行化因子。工作单元会排入队列并在有可用的槽时执行。
如果查询所需的槽数超出了您承诺使用的槽数,系统不会向您收取额外槽的费用,也不会根据额外的按需使用费率收取相关费用。您的各个工作单元会排队等候。
例如,
- 查询阶段请求 2000 个槽,但只有 1000 个槽可用。
- BigQuery 会将 1000 个可用槽全部占用,并将另外 1000 个槽排入队列。
- 此后,如果有 100 个槽完成了其工作,那么这些槽会从 1000 个已排入队列的工作单元中动态选取 100 个工作单元。其余的 900 个已排入队列的工作单元继续保留。
- 此后,如果有 500 个槽完成了其工作,那么这些槽会从 900 个已排入队列的工作单元中动态选取 500 个工作单元。其余的 400 个已排入队列的工作单元继续保留。
BigQuery 公平调度机制
BigQuery 使用一种称为公平调度的算法在单个预留中分配槽容量。
BigQuery 调度器会强制先在一个预留中正在运行的查询所属的各项目之间均匀共享槽,然后再在给定项目的作业内进行共享。调度器提供最终公平性。在短时间内,某些作业可能会获得不成比例的槽,但调度器最终会纠正此情况。调度器的目标是在主动逐出正在运行的任务(导致浪费槽时间)和过于宽松的逐出(导致包含长时间运行的任务的作业获得不成比例的槽时间)之间找到平衡点。
公平调度机制可确保所有查询都可以随时访问所有可用槽,并且系统可以自动根据每个活跃查询的容量需求变化在这些查询之间动态地重新分配容量。在以下情况下,您可以在查询完成后提交新的查询来执行:
- 只要您提交新的查询,系统就会自动在各执行中查询之间重新分配容量。当每个查询的可用容量增加时,个别工作单元可以正常暂停、恢复及排入队列。
- 每当有查询完成时,该查询使用的容量都会自动立即提供给其他所有查询使用。
- 只要查询的容量需求因查询动态 DAG 的更改而发生变化,BigQuery 就会自动重新评估此查询和其他所有查询的可用容量,并根据需要重新分配和暂停槽。
根据查询的复杂性和大小,查询可能并不需要其有权使用的所有槽,也可能需要使用更多的槽。在公平调度机制的作用下,BigQuery 会动态地确保所有槽在任何时间点都会得到充分利用。
如果某个重要的作业需要的槽数始终比它从调度器接收到的槽数多,请考虑创建一个具有所需槽数的额外预留,并将该作业分配给该预留。
下面以公平调度为例,假设您有以下预留配置:
- 预留
A
,具有 1,000 个基准槽,没有自动扩缩功能 - 已分配到您的预留的项目
A
和项目B
情形 1:在项目 A
中,您运行需要高槽使用率的查询 A
(一个并发查询);在项目 B
中,您运行 20 个并发查询。即使总共有 21 个查询在使用预留 A
,槽分布如下:
- 项目
A
获得 500 个槽,查询A
使用 500 个槽运行。 - 项目
B
获得 500 个槽,供其 20 个查询共同使用。
情形 2:在项目 A
中,您运行需要 100 个槽的查询 A
(一个并发查询);在项目 B
中,您运行 20 个并发查询。由于查询 A
不需要预留的 50% 的槽,因此槽分布如下:
- 项目
A
获得 100 个槽,查询A
使用 100 个槽运行。 - 项目
B
获得 900 个槽,供其 20 个查询共同使用。
反之,请考虑以下预留配置:
- 预留
B
,具有 1,000 个基准槽,没有自动扩缩功能。 - 10 个项目,全部分配给预留
B
。
假设这 10 个项目正在运行的查询有足够的槽需求,那么无论每个项目正在运行多少个查询,每个项目都会获得总预留槽数的 1/10(即 100 个槽)。
Slot 配额和限制
槽配额和限制可为 BigQuery 提供安全保障。不同的定价模式使用不同的 slot 配额类型,如下所示:
按需价格模式:您受每个项目和组织的槽限制的约束,且具有瞬时突发功能。根据工作负载的情况,可用的槽越多,查询性能也就越高。
基于容量的价格模式:预留配额和限制定义了您可以在一个位置的所有预留中分配的槽数上限。您只需为预留和承诺付费,无需为配额付费。 如需了解如何增加槽配额,请参阅申请增加配额。
如需查看您使用的槽数,请参阅 BigQuery 监控。
空闲槽
在任何给定时间,某些槽都可能处于空闲状态。这可能包括:
- 未分配给任何预留基准的槽承诺。
- 分配给预留基准但未使用的槽。
使用按需价格模式时,空闲 slot 不适用。
默认情况下,在预留中运行的查询自动使用来自同一管理项目中的其他预留的空闲槽。BigQuery 会在需要时立即将槽分配给指定的预留。被其他预留使用的空闲槽会被快速抢占。在短时间内,您可能会看到所有预留的总槽消耗量超过您指定的最大值,但您无需为这部分额外的槽用量付费。
例如,假设您有以下预留设置:
project_a
分配给reservation_a
,后者有 500 个基准槽,但没有自动扩缩。project_b
分配给reservation_b
,后者有 100 个基准槽,但没有自动扩缩槽。- 这两个预留位于同一管理项目中,并且没有其他项目分配给这些预留。
您在 project_b
中运行 query_b
。如果 project_a
中没有运行任何查询,则 query_b
可以使用 reservation_a
中的 500 个空闲槽。在 query_b
仍在运行时,它最多可以使用 600 个槽:100 个基准槽加上 500 个空闲槽。
假设在 query_b
运行时,您在 project_a
中运行 query_a
,该 project_a
可以使用 500 个槽。
- 由于您为
project_a
预留了 500 个基准槽,因此query_a
会立即启动并分配到 500 个槽。 - 分配给
query_b
的槽数快速减少到 100 个基准槽。 - 在
project_b
中运行的其他查询会共享这 100 个槽。如果后续查询没有足够的槽来启动,则它们会排队,直到正在运行的查询完成并且有槽可用为止。
在此示例中,如果 project_b
被分配给没有基准槽或自动扩缩的预留,则在 query_a
开始运行后,query_b
将没有槽。BigQuery 会暂停 query_b
,直到有空闲槽可用或查询超时。project_b
中的其他查询会排队,直到有空闲槽可用。
为确保预留仅使用预配的槽,请将 ignore_idle_slots
设置为 true
。不过,ignore_idle_slots
设置为 true
的预留可以与其他预留共享其空闲槽。
您不能在不同版本的预留之间共享空闲槽。您只能共享基准槽或承诺槽。自动扩缩的槽可能暂时可用,但无法作为其他预留的空闲槽进行共享,因为它们可能会缩容。
只要 ignore_idle_slots
为 false,即使预留的槽数为 0
,也仍然可以访问未使用的槽。如果您仅使用 default
预留,则最好关闭 ignore_idle_slots
。然后,您可以向该预留分配项目或文件夹,并且它仅使用空闲槽。
ML_EXTERNAL
类型的分配例外,因为 BigQuery ML 外部模型创建作业使用的槽不是可抢占的。具有 ML_EXTERNAL
和 QUERY
分配类型的预留中的槽只有在未被 ML_EXTERNAL
作业占用情况下才能供其他查询作业使用。此外,这些作业无法使用其他预留中的空闲槽。
基于预留的公平性
借助基于预留的公平性,BigQuery 会优先处理同一管理项目中的所有预留,并为这些预留平均分配空闲槽,无论每个预留中有多少个项目在运行作业。每个预留都会获得空闲槽池中类似比例的可用容量,然后其槽会在项目内均匀分配。此功能仅在企业版或企业 Plus 版中受支持。
下图显示了在未启用基于预留的公平性时,空闲 slot 的分配情况:
在此图表中,空闲槽在各个项目之间平均分配。
如果未启用基于预留的公平性,则可用的空闲槽会在预留中的项目之间均匀分配。
下图显示了在启用基于预留的公平性后,空闲时段的分配情况:
在此图表中,空闲槽在预留之间平均分配,而不是在项目之间平均分配。
启用基于预留的公平性后,可用的空闲槽会在各个预留之间平均分配。
启用基于预留的公平性后,请查看资源消耗情况,以便管理槽可用性和查询性能。
对于时间要求严格的生产工作负载,请避免仅依赖空闲槽,这些作业应使用基准槽或自动扩缩槽。我们建议将空闲 slot 用于优先级较低的作业,因为这些 slot 可随时被抢占。
槽用量过高
如果作业占用槽的时间过长,可能会获得不公平的槽份额。为防止延迟,BigQuery 允许其他作业借用额外的槽,从而导致总槽使用量在一段时间内超过您指定的槽容量。任何过多的槽用量都仅归因于获得超过其公平份额的作业。
超出部分的槽位不会直接向您收取费用。相反,作业会继续运行,并以公平份额累积槽使用量,直到所有超额使用量都由您分配的容量覆盖为止。报告的 slot 使用情况中不包含多余的 slot,但某些详细的执行统计信息除外。
请注意,有时会预先借用一些时段,以减少未来的延迟并提供其他好处,例如降低时段费用变动和缩短尾部延迟时间。槽位借用仅限于您总槽位容量的一小部分。