了解槽
BigQuery 槽是 BigQuery 执行 SQL 查询的虚拟 CPU。在查询执行期间,BigQuery 会根据查询大小和复杂程度,自动计算查询所需的槽数。
您可以选择使用按需价格模式,也可以选择基于容量的价格模式。两种模式均使用槽进行数据处理。使用基于容量的价格模式,您可以为专用或自动扩缩的查询处理容量付费。基于容量的价格模式可让您明确控制槽和分析容量,但按需价格模式无法做到。
使用基于容量的价格模式的客户可明确选择要预留的槽数。查询会在该容量内运行,并且在部署该容量后需要为其持续支付费用。例如,如果您购买 2,000 个 BigQuery 槽,则在任何给定时间,查询总共只能使用 2,000 个虚拟 CPU。在删除之前,您拥有 2,000 个槽的容量,并需要为其付费。
采用 BigQuery 按需价格模式的项目受每个项目槽配额的限制,且具有瞬时突发功能。对于大多数采用按需模式的用户而言,默认槽容量绰绰有余。根据工作负载的实际情况,访问的槽越多,查询性能也就越高。如需检查您的账号使用的槽数,请参阅 BigQuery 监控。
估算要购买的槽数
BigQuery 的架构支持通过增加资源来高效扩容。根据工作负载的实际情况,增加容量可能会为您带来更多益处。因此,选择最佳的槽购买数取决于您对性能、吞吐量和效用的要求。
您可以使用基准槽和自动扩缩槽进行实验,以确定最佳槽配置。例如,您可以依次使用 500 个基准槽、1,000 个槽、1,500 个槽和 2,000 个槽来测试工作负载,并观察这些槽数量对性能的影响。
您还可以检查项目当前的槽使用量以及您每月希望支付的费用。按需结算工作负载存在 2000 个槽的软上限,但重要的是使用 INFORMATION_SCHEMA.JOBS*
视图、Cloud Logging、Jobs API 或 BigQuery 审核日志检查您的项目目前实际使用了多少个槽。如需了解详情,请参阅直观显示可用的槽和分配的槽。
购买槽并运行工作负载至少七天后,您可以使用槽估算器来分析性能并模拟添加或减少槽的效果。如需了解详情,请参阅估算槽容量要求。
使用槽执行查询
BigQuery 在执行查询作业时,会将声明性 SQL 语句转换为执行图。此执行图会分解为一系列查询阶段,而这些阶段本身是由多组更精细的执行步骤组成。BigQuery 会利用高度分布式的并行架构来运行这些查询,而这些阶段则会建立许多潜在工作器可能并行执行的工作单元模型。各阶段会使用快速分布式 Shuffle 架构相互通信,Google Cloud 博客详细介绍了该架构。
BigQuery 查询执行过程是动态的,也就是说,您可以在查询执行期间修改查询计划。在查询运行时引入的阶段通常用于改进所有查询工作器的数据分布。
BigQuery 可以并发运行多个阶段。 BigQuery 可使用推测性执行技术来加速查询,并可动态地重新划分阶段以实现最佳并行性。
在查询的每个阶段,BigQuery 槽会执行个别工作单元。例如,如果 BigQuery 确定某一阶段的最佳并行化因子为 10,则它会请求 10 个槽以用于处理该阶段。
在槽资源不足的情况下执行查询
如果查询请求的槽数超过当前可用的槽数,BigQuery 会将个别工作单元排入队列,并等待槽变为可用状态。随着查询继续执行以及槽被释放,系统会动态地选取这些已排入队列的工作单元用于执行。
BigQuery 可以为查询的特定阶段请求任意数量的槽。所请求的槽数与您购买的容量无关,而是指示 BigQuery 为该阶段选择的最佳并行化因子。工作单元会排入队列并在有可用的槽时执行。
如果查询所需的槽数超出了您承诺使用的槽数,系统不会向您收取额外槽的费用,也不会根据额外的按需使用费率收取相关费用。您的各个工作单元会排队等候。
例如,
- 查询阶段请求 2000 个槽,但只有 1000 个槽可用。
- BigQuery 会将 1000 个可用槽全部占用,并将另外 1000 个槽排入队列。
- 此后,如果有 100 个槽完成了其工作,那么这些槽会从 1000 个已排入队列的工作单元中动态选取 100 个工作单元。其余的 900 个已排入队列的工作单元继续保留。
- 此后,如果有 500 个槽完成了其工作,那么这些槽会从 900 个已排入队列的工作单元中动态选取 500 个工作单元。其余的 400 个已排入队列的工作单元继续保留。
空闲槽
在任何给定时间,某些槽都可能处于空闲状态。这可能包括:
- 未分配给任何预留基准的槽承诺。
- 分配给预留基准但未使用的槽。
默认情况下,在预留中运行的查询自动使用来自同一管理项目中的其他预留的空闲槽。当需要时,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 使用一种称为公平调度的算法在单个预留中分配槽容量。
BigQuery 调度器会强制先在一个预留中正在运行的查询所属的各项目之间均匀共享槽,然后再在给定项目的作业内进行共享。调度器提供最终公平性。在短时间内,某些作业可能会获得不成比例的槽,但调度器最终会纠正此情况。调度器的目标是在主动逐出正在运行的任务(导致浪费槽时间)和过于宽松的逐出(导致包含长时间运行的任务的作业获得不成比例的槽时间)之间找到平衡点。
如果某个重要的作业需要的槽数始终比它从调度器接收到的槽数多,请考虑创建一个具有保证槽数的额外预留,并将该作业分配给该预留。
槽用量超标
如果作业占用槽的时间过长,则可能会获得不公平的槽分配比例(如上文所述)。为防止延迟,其他作业可以借用额外的槽,导致槽总用量在某些时间段超出您指定的槽容量。任何超出槽用量的用量都仅归因于获得超出其公平份额的作业。
我们不会直接向您收取超出数量的槽位费用。相反,作业会继续运行,并按其公平份额累积槽用量,直到其所有超额用量都由您的常规容量覆盖。报告的槽用量不包括超出槽数的槽,但某些详细的执行统计信息除外。
请注意,系统可能会抢先借用一些槽,以减少未来的延迟,并提供其他好处,例如降低槽费用波动性和尾端延迟时间。槽借用仅限于占总槽容量的一小部分。
BigQuery 公平调度机制
槽在项目之间均匀分布,然后在项目中的作业内分布。 这意味着所有查询都可以随时访问所有可用槽,并且系统可以自动根据每个活跃查询的容量需求变化在这些查询之间动态地重新分配容量。在以下情况下,您可以在查询完成后提交新的查询来执行:
- 只要您提交新的查询,系统就会自动在各执行中查询之间重新分配容量。当每个查询的可用容量增加时,个别工作单元可以正常暂停、恢复及排入队列。
- 每当有查询完成时,该查询使用的容量都会自动立即提供给其他所有查询使用。
- 只要查询的容量需求因查询动态 DAG 的更改而发生变化,BigQuery 就会自动重新评估此查询和其他所有查询的可用容量,并根据需要重新分配和暂停槽。
根据查询的复杂性和大小,查询可能并不需要其有权使用的所有槽,也可能需要使用更多的槽。在公平调度机制的作用下,BigQuery 会动态地确保所有槽在任何时间点都会得到充分利用。