了解槽
BigQuery 槽是 BigQuery 执行 SQL 查询或其他作业类型的虚拟计算单元。在执行查询期间,BigQuery 会自动确定查询使用的槽数。使用的槽数取决于要处理的数据量、查询的复杂性以及可用槽数。通常,可用的槽越多,您可以运行的并发查询就越多,并且复杂查询可以运行得更快。
虽然所有查询都使用槽,但您可以选择两种使用费用结算方式:按需价格模式或基于容量的价格模式。
默认情况下,系统会采用按需模式结算。采用此模式时,您需要为每个查询处理的数据量(以 TiB 为单位)付费。采用按需价格模式的项目受每个项目和每个组织的槽数限制的约束,且具有瞬时突发功能。对于大多数采用按需模式的用户而言,槽容量上限绰绰有余。不过,根据工作负载的情况,可用的槽越多,查询性能也就越高。如需检查您的账号使用的槽数,请参阅 BigQuery 监控。
使用基于容量的价格模式时,您需要为查询随时间推移分配的槽容量付费。这种模式可让您明确控制总槽容量,但按需模式无法做到。您可以通过预订明确选择要使用的槽数。您可以将预留中的槽数指定为始终分配的基准数量,也可以指定为需要时分配的自动缩放数量。
使用槽执行查询
BigQuery 在执行查询作业时,会将 SQL 语句转换为执行计划。此执行计划会分解为一系列查询阶段,而这些阶段本身是由多组更精细的执行步骤组成。BigQuery 会利用高度分布式的并行架构来运行这些查询,而这些阶段则会建立许多潜在工作器可能并行执行的工作单元模型。数据会使用快速分布式 Shuffle 架构在各个阶段之间传递,Google Cloud 博客详细介绍了该架构。
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 会动态地确保所有槽在任何时间点都会得到充分利用。
如果某个重要的作业需要的槽数始终比它从调度器接收到的槽数多,请考虑创建一个具有所需槽数的额外预留,并将该作业分配给该预留。
槽配额和限制
槽配额和限制可为 BigQuery 提供安全保障。不同的定价模式使用不同的槽位配额类型,如下所示:
按需价格模式:您受每个项目和组织的槽数限制的约束,且具有瞬时突发功能。根据工作负载的情况,可用的槽越多,查询性能也就越高。
基于容量的价格模式:预留配额和限制定义了您可以在一个位置为所有预留分配的槽数上限。您只需为预留和承诺付费,无需为配额付费。如需了解如何增加槽配额,请参阅申请增加配额。
如需查看您使用的槽数,请参阅 BigQuery 监控。
空闲槽
在任何给定时间,某些槽都可能处于空闲状态。这可能包括:
- 未分配给任何预留基准的槽承诺。
- 分配给预留基准但未使用的槽。
使用按需价格模式时,空闲时段不适用。
默认情况下,在预留中运行的查询自动使用来自同一管理项目中的其他预留的空闲槽。当需要时,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_b
在 query_a
开始运行后将没有槽。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 允许其他作业借用额外的槽,导致槽总用量在某些时间段超过您指定的槽容量。任何超出槽用量的用量都仅归因于获得超出其公平份额的作业。
我们不会直接向您收取超额槽位的费用。相反,作业会继续运行,并按其公平份额累积槽用量,直到其所有超额用量都由您分配的容量覆盖为止。报告的槽用量不包括超出槽数的槽,但某些详细的执行统计信息除外。
请注意,系统可能会抢先借用一些槽,以减少未来的延迟,并提供其他好处,例如降低槽费用波动性和尾延迟时间。槽借用仅限于占总槽容量的一小部分。