排查查询问题

本文档旨在帮助您排查与运行查询相关的常见问题,例如确定查询速度缓慢的原因,或针对失败查询返回的常见错误提供解决步骤。

排查查询速度缓慢问题

在排查查询性能缓慢问题时,请考虑以下常见原因:

  1. 查看Google Cloud Service Health 页面,了解可能影响查询性能的已知 BigQuery 服务中断情况。

  2. 作业详情页面上查看查询的作业时间轴,了解查询的每个阶段的运行时长。

    • 如果大部分所用时间是由于创建时间较长,请与 Cloud Customer Care 团队联系以获取帮助。

    • 如果大部分所用时间是由于执行时间较长,请查看查询性能数据分析。查询性能数据分析可告知您查询运行时间是否超过平均执行时间,并针对可能的原因提供建议。可能的原因包括查询槽争用或 Shuffle 配额不足。如需详细了解每种查询性能问题及其可能的解决方法,请参阅解读查询性能数据分析

  3. 查看查询作业 JobStatistics 中的 finalExecutionDurationMs 字段。查询可能已重试。finalExecutionDurationMs 字段包含此作业最终尝试执行时长(以毫秒为单位)。

  4. 查看查询作业详情页面中处理的字节数,了解是否高于预期。为此,您可以将当前查询处理的字节数与在可接受的时间量内完成的其他查询作业进行比较。如果两个查询处理的字节数存在较大差异,则可能是由于数据量较大而导致查询速度缓慢。如需了解如何优化查询以处理大量数据,请参阅优化查询计算

    您还可以使用 INFORMATION_SCHEMA.JOBS 视图搜索成本最高的查询,从而确定项目中处理大量数据的查询。

比较同一查询的慢速执行和快速执行

如果之前运行很快的查询现在运行缓慢,请检查 Job API 对象输出,以确定其执行方面的变化。

缓存命中

通过查看 cacheHit 值,确认作业的快速执行是否为缓存命中。如果值为 true,表示查询快速执行,则查询使用了缓存的结果,而不是执行查询。

如果您预计缓慢的作业会使用缓存的结果,请调查该查询不再使用缓存的结果的原因。 如果您不希望查询从缓存中检索数据,请查找未命中缓存的快速查询执行示例以进行调查。

配额延迟

如需确定减速是否由任何配额延迟导致,请检查这两个作业的 quotaDeferments 字段。比较这些值,以确定较慢查询的开始时间是否因任何未影响较快作业的配额延迟而延迟。

执行时长

如需了解这两个作业的最后一次尝试的执行时长之间的差异,请比较它们的 finalExecutionDurationMs 字段的值。

如果 finalExecutionDurationMs 的值非常相似,但两个查询的实际执行时间(计算方式为 startTime - endTime)相差很大,则表示速度较慢的作业可能因暂时性问题而进行了内部查询执行重试。如果您反复看到这种差异模式,请与 Cloud Customer Care 团队联系以获取帮助

处理的字节数

查看查询作业详情页面中处理的字节数,或查看 JobStatistics 中的 totalBytesProcessed,了解是否高于预期。如果两个查询处理的字节数存在较大差异,则可能是由于处理的数据量发生变化而导致查询速度缓慢。如需了解如何优化查询以处理大量数据,请参阅优化查询计算。 以下原因可能会导致查询处理的字节数增加:

  • 查询所引用的表的大小有所增加。
  • 查询现在读取的是表的较大分区。
  • 查询引用了定义已更改的视图。

被引用表

通过分析 JobStatistics2referencedTables 字段的输出,检查查询是否读取了相同的表。引用表中的差异可归因于以下原因:

  • SQL 查询已修改为读取不同的表。比较查询文本以确认这一点。
  • 在查询的执行之间,视图定义发生了变化。检查此查询中引用的视图的定义,并根据需要更新这些定义

被引用表中的差异可能可以解释 totalBytesProcessed 中的变化。

物化视图使用情况

如果查询引用了任何具体化视图,则性能差异可能是由查询执行期间选择或拒绝具体化视图造成的。检查 MaterializedViewStatistics,了解快速查询中使用的任何物化视图是否在慢速查询中被拒绝。查看 MaterializedView 对象中的 chosenrejectedReason 字段。

元数据缓存统计信息

对于涉及启用了元数据缓存的 Amazon S3 BigLake 表或 Cloud Storage BigLake 表的查询,请比较 MetadataCacheStatistics 的输出,以检查慢速查询和快速查询之间的元数据缓存使用情况是否存在差异,并了解相应原因。例如,元数据缓存可能位于表的 maxStaleness 窗口之外。

比较 BigQuery BI Engine 统计信息

如果查询使用 BigQuery BI Engine,请分析 BiEngineStatistics 的输出,以确定是否对慢速查询和快速查询应用了相同的加速模式。查看 BiEngineReason 字段,了解部分加速或完全不加速的高级原因,例如内存不足、缺少预留或输入过大。

查看查询性能数据分析的差异

通过查看 Google Cloud 控制台中的执行图StagePerformanceStandaloneInsight 对象,比较每个查询的查询性能数据分析,了解以下可能存在的问题:

请注意为慢速作业提供的数据分析,以及为快速作业生成的数据分析之间的差异,以确定影响性能的阶段变化。

如需更全面地分析作业执行元数据,您需要比较两个作业的 ExplainQueryStage 对象,从而了解查询执行的各个阶段。

首先,请查看解读查询阶段信息部分中介绍的 Wait msShuffle output bytes 指标。

INFORMATION_SCHEMA.JOBS 视图中的资源警告

查询 INFORMATION_SCHEMA.JOBS 视图query_info.resource_warning 字段,以查看 BigQuery 分析的警告与所用资源之间是否存在差异。

工作负载统计信息分析

可用的槽资源和槽争用会影响查询执行时间。 以下部分可帮助您了解特定查询运行的槽用量和可用性。

每秒平均槽数

如需计算查询每毫秒使用的平均槽数,请将作业的槽毫秒数值(即 JobStatistics2 中的 totalSlotMs)除以相应作业最终尝试执行的时长(以毫秒为单位,即 JobStatistics 中的 finalExecutionDurationMs)。

您还可以通过查询 INFORMATION_SCHEMA.JOBS 视图来计算作业每毫秒使用的平均槽数

如果作业执行的工作量相似,但每秒的平均槽位数更多,则完成速度会更快。每秒平均槽用量较低可能是由以下原因造成的:

  1. 由于不同作业之间存在资源争用,因此没有可用的额外资源 - 预留已达到上限。
  2. 作业在执行的大部分时间里都没有请求更多 slot。例如,当存在数据倾斜时,可能会发生这种情况。

工作负载管理模型和预留大小

如果您使用按需结算模式,则每个项目可使用的槽数有限。此外,如果特定位置的按需容量有大量争用,您可用的槽也可能偶尔会减少。

基于容量的模式更具可预测性,可让您指定有保证的基准槽数。

在比较使用按需付费的查询执行运行与使用预留的查询执行时,请考虑这些差异。

建议使用预留,以获得稳定可预测的查询执行性能。如需详细了解按需工作负载与基于容量的工作负载之间的区别,请参阅工作负载管理简介

作业并发

作业并发表示查询执行期间作业对 slot 资源的竞争。作业并发性越高,作业执行速度通常越慢,因为作业可用的槽位越少。

您可以查询 INFORMATION_SCHEMA.JOBS 视图,以查找在项目中与特定查询同时运行的并发作业的平均数量

如果预留分配了多个项目,请修改查询以使用 JOBS_BY_ORGANIZATION 而不是 JOBS_BY_PROJECT,从而获取准确的预留级数据。

与快速作业相比,缓慢作业执行期间的平均并发性更高,这是导致整体缓慢的一个因素。

考虑通过以下方式减少项目或预留中的并发数:将资源密集型查询分散到预留或项目内的不同时间,或者分散到不同的预留或项目中。

另一种解决方案是购买预留或增加现有预留的大小。考虑允许预留使用空闲槽

如需了解要添加多少个槽,请参阅估算槽容量要求

如果预留分配给多个项目,则在平均作业并发数相同的情况下,在不同项目中运行的作业可能会获得不同的槽分配结果。如需了解详情,请参阅公平调度

预留利用率

您可以使用管理员资源图表BigQuery Cloud Monitoring 来监控预留利用率。如需了解详情,请参阅监控 BigQuery 预留

如需了解作业是否请求了任何额外的 slot,请查看估计的可运行单元数指标,该指标在作业 API 响应中为 estimatedRunnableUnits,在 INFORMATION_SCHEMA.JOBS_TIMELINE 视图中为 period_estimated_runnable_units。 如果此指标的值大于 0,则表示相应作业当时可以从额外的 slot 中获益。 如需估算作业执行时间中作业本可受益于额外槽的时间百分比,请针对 INFORMATION_SCHEMA.JOBS_TIMELINE 视图运行以下查询:

SELECT
  ROUND(COUNTIF(period_estimated_runnable_units > 0) / COUNT(*) * 100, 1) AS execution_duration_percentage
FROM `myproject`.`region-us`.INFORMATION_SCHEMA.JOBS_TIMELINE
WHERE job_id = 'my_job_id'
GROUP BY job_id;
结果类似于以下内容:
+---------------------------------+
|   execution_duration_percentage |
+---------------------------------+
|                            96.7 |
+---------------------------------+

百分比较低意味着,在这种情况下,槽资源可用性不是导致查询速度缓慢的主要因素。

如果百分比较高,但预留在此期间未得到充分利用,请与 Cloud Customer Care 团队联系以进行调查。

如果预留在作业执行缓慢期间得到充分利用,且百分比较高,则说明作业受到资源限制。请考虑减少并发数、增加预留大小、允许预留使用空闲槽,或者购买预留(如果作业是按需运行的)。

作业元数据和工作负载分析结果不确定

如果您仍然找不到原因来解释查询性能低于预期的原因,请与 Cloud Customer Care 团队联系以获取帮助。

使用 gcpdiag 排查查询失败问题

gcpdiag 是一种开源工具,不是官方支持的 Google Cloud 产品。您可以使用 gcpdiag 工具来帮助识别和修复 Google Cloud项目问题。如需了解详情,请参阅 GitHub 上的 gcpdiag 项目

借助 gcpdiag 工具,您可以分析失败的 BigQuery 查询,了解特定失败是否存在已知的根本原因和缓解措施。

运行 gcpdiag 命令

您可以通过 Google Cloud CLI 运行 gcpdiag 命令:

Google Cloud 控制台

  1. 完成然后复制以下命令。
  2. gcpdiag runbook bigquery/failed_query \
       --parameter project_id=PROJECT_ID \
       --parameter bigquery_job_region=JOB_REGION \
       --parameter bigquery_job_id=JOB_ID \
       --parameter bigquery_skip_permission_check=SKIP_PERMISSION_CHECK
  3. 打开 Google Cloud 控制台并激活 Cloud Shell。
  4. 打开 Cloud 控制台
  5. 粘贴复制的命令。
  6. 运行 gcpdiag 命令以下载 gcpdiag Docker 映像,然后执行诊断检查。如果适用,请按照输出说明修复失败的检查。

Docker

您可以使用封装容器运行 gcpdiag,以在 Docker 容器中启动 gcpdiag。必须安装 Docker 或 Podman

  1. 在本地工作站上复制并运行以下命令。
    curl https://gcpdiag.dev/gcpdiag.sh >gcpdiag && chmod +x gcpdiag
  2. 执行 gcpdiag 命令:
    ./gcpdiag runbook bigquery/failed_query \
       --parameter project_id=PROJECT_ID \
       --parameter bigquery_job_region=JOB_REGION \
       --parameter bigquery_job_id=JOB_ID \
       --parameter bigquery_skip_permission_check=SKIP_PERMISSION_CHECK

查看此 Runbook 的可用参数

替换以下内容:

  • PROJECT_ID:资源所在项目的 ID。
  • JOB_REGION:执行 BigQuery 作业的区域。
  • JOB_ID:相应 BigQuery 作业的作业标识符。
  • SKIP_PERMISSION_CHECK:(可选)如果您想跳过相关权限检查并加快 Runbook 执行速度,请将此值设置为 True(默认值为 False)。

实用标志:

如需查看所有 gcpdiag 工具标志的列表和说明,请参阅 gcpdiag 使用说明

Avro 架构解析

错误字符串:Cannot skip stream

加载具有不同架构的多个 Avro 文件时,可能会发生此错误,从而导致架构解析问题,并导致导入作业在某个随机文件失败。

如需解决此错误,请确保加载作业中按字母排序的最后一个文件包含不同架构的超集(并集)。这是基于 Avro 如何处理架构解析的要求。

冲突的并发查询

错误字符串:Concurrent jobs in the same session are not allowed

如果在一个会话中并行运行多个查询,就可能会发生此错误,因为这是不受支持的。请参阅会话限制

冲突的 DML 语句

错误字符串:Could not serialize access to table due to concurrent update

如果在同一表上并发运行的多个变更型数据操纵语言 (DML) 语句彼此冲突,或者表在变更型 DML 语句执行期间被截断,就可能会发生此错误。如需了解详情,请参阅 DML 语句冲突

如需解决此错误,请运行影响单个表的 DML 操作,以避免重叠。

相关子查询

错误字符串:Correlated subqueries that reference other tables are not supported unless they can be de-correlated

如果您的查询包含引用子查询外部的列(称为相关性列)的子查询,则可能会发生此错误。系统会使用效率低下的嵌套执行策略来计算相关子查询,在这种策略中,系统会在生成相关性列的外部查询中针对每一行来计算子查询。有时,BigQuery 可以在内部使用相关子查询重写查询,以便更高效地执行查询。当 BigQuery 无法充分优化查询时,就会发生相关子查询错误。

如需解决此错误,请尝试以下操作:

  • 从子查询中移除任何 ORDER BYLIMITEXISTSNOT EXISTSIN 子句。
  • 使用多语句查询创建要在子查询中引用的临时表。
  • 重写查询,以改用 CROSS JOIN

列级访问权限控制权限不足

错误字符串:Requires fineGrainedGet permission on the read columns to execute the DML statements

当您尝试执行 DML DELETEUPDATEMERGE 语句时,如果您对使用列级访问权限控制来限制列级访问的扫描列没有 Fine-Grained Reader 权限,则会出现此错误。如需了解详情,请参阅列级访问权限控制对写入的影响

计划查询的凭据无效

错误字符串:

  • Error code: INVALID_USERID
  • Error code 5: Authentication failure: User Id not found
  • PERMISSION_DENIED: BigQuery: Permission denied while getting Drive credentials

如果计划的查询因凭据过期而失败,就可能会发生此错误,尤其是在查询 Google 云端硬盘数据时。

要解决此错误,请按照以下步骤操作:

服务账号凭证无效

错误字符串:HttpError 403 when requesting returned: The caller does not have permission

当您尝试使用服务账号设置计划查询时,可能会出现此错误。如需解决此错误,请参阅授权和权限问题中的问题排查步骤。

快照时间无效

错误字符串:Invalid snapshot time

如果您尝试查询数据集时间旅行窗口之外的历史数据,就可能会发生此错误。如需解决此错误,请更改查询以访问数据集时间旅行窗口内的历史数据。

如果查询中使用的某个表在查询开始后被删除并重新创建,也可能会发生此错误。检查是否存在执行此操作的计划查询或应用与失败查询同时运行。如果存在,请尝试将执行删除和重新创建操作的进程移到与读取该表的查询不冲突的时间运行。

作业已存在

错误字符串:Already Exists: Job <job name>

如果查询作业必须对大型数组进行求值从而导致创建查询作业的时间超过平均耗时,就可能会发生此错误。例如,具有 WHERE 子句(如 WHERE column IN (<2000+ elements array>))的查询。

要解决此错误,请按照以下步骤操作:

如果您手动设置了作业 ID,但作业未在超时期限内返回成功,也可能会出现此错误。在这种情况下,您可以添加异常处理程序来检查作业是否存在。如果作业已完成,您可以从作业中拉取查询结果。

未找到作业

错误字符串:Job not found

响应未为 location 字段指定任何值的 getQueryResults 调用时,可能会发生此错误。如果是这种情况,请重试调用并提供 location 值。

如需了解详情,请参阅避免对相同的通用表表达式 (CTE) 进行多次求值

找不到位置

错误字符串:Dataset [project_id]:[dataset_id] was not found in location [region]

当您引用不存在的数据集资源,或请求中的位置与数据集的位置不匹配时,系统会返回此错误。

如需解决此问题,请在查询中指定数据集的位置,或确认数据集在同一位置可用。

查询超出执行时间限制

错误字符串:Query fails due to reaching the execution time limit

如果您的查询达到了查询执行时间限制,请使用类似于以下示例的查询查询 INFORMATION_SCHEMA.JOBS 视图,检查之前运行的查询的执行时间:

SELECT TIMESTAMP_DIFF(end_time, start_time, SECOND) AS runtime_in_seconds
FROM `region-us`.INFORMATION_SCHEMA.JOBS
WHERE statement_type = 'QUERY'
AND query = "my query string";

如果之前运行的查询花费的时间大幅减少,请使用查询性能数据分析来确定并解决根本问题。

查询响应内容过大

错误字符串:responseTooLarge

如果查询结果超过响应大小上限,就会发生此错误。

如需解决此错误,请按照错误表格中为 responseTooLarge 错误消息提供的指南操作。

未找到预订或预订缺少时段

错误字符串:Cannot run query: project does not have the reservation in the data region or no slots are configured

如果查询区域中分配给项目的预留的槽数为零,则会发生此错误。您可以向预留添加槽,允许预留使用空闲槽,使用其他预留,或者移除分配并按需运行查询。

找不到表

错误字符串:Not found: Table [project_id]:[dataset].[table_name] was not found in location [region]

当查询中的某个表在您指定的数据集或区域中找不到时,就会发生此错误。如需解决此错误,请执行以下操作:

  • 检查您的查询是否包含正确的项目、数据集和表名称。
  • 检查表是否存在于您运行查询的区域中。
  • 确保在作业执行期间未删除并重新创建该表。否则,不完整的元数据传播可能会导致此错误。

DML 语句过多

错误字符串:Too many DML statements outstanding against <table-name>, limit is 20

如果队列中单个表有超过 20 个 DML 语句处于 PENDING 状态,则会出现此错误。如果您针对单个表提交 DML 作业的速度快于 BigQuery 的处理速度,通常会发生此错误。

一种可能的解决方案是将多个较小的 DML 操作合并为一组,形成较大但数量更少的作业,例如通过批量更新和插入。将较小的作业组合为较大的作业时,运行较大作业的开销会被分摊,执行速度会更快。整合影响相同数据的 DML 语句通常会提高 DML 作业的效率,并且不太可能超出队列大小配额限制。如需详细了解如何优化 DML 操作,请参阅避免用于更新或插入单行的 DML 语句

提高 DML 效率的其他解决方案包括对表进行分区或聚簇。如需了解详情,请参阅最佳做法

由于并发更新,事务已中止

错误字符串:Transaction is aborted due to concurrent update against table [table_name]

如果两个不同的变更型 DML 语句尝试同时更新同一表,则可能会发生此错误。例如,假设您在包含变更型 DML 语句的会话中启动事务,随后出现错误。如果没有异常处理程序,BigQuery 会在会话结束时自动回滚事务,这最多需要 24 小时。在此期间,其他尝试在表上运行变更型 DML 语句的操作会失败。

如需解决此错误,请列出您的活跃会话,并检查其中是否有任何会话包含状态为 ERROR 的查询作业,该作业对表运行了变更型 DML 语句。然后,终止该会话。

用户没有权限

错误字符串:

  • Access Denied: Project [project_id]: User does not have bigquery.jobs.create permission in project [project_id].
  • User does not have permission to query table project-id:dataset.table.
  • Access Denied: User does not have permission to query table or perhaps it does not exist.

在运行查询时,如果您对从中运行查询的项目没有 bigquery.jobs.create 权限,则可能会发生这些错误,无论您对包含数据的项目拥有何种权限。

如果您的服务账号、用户或群组对查询引用的所有表和视图没有 bigquery.tables.getData 权限,您也可能会收到这些错误。如需详细了解运行查询所需的权限,请参阅所需角色

如果表不存在于所查询的区域(例如 asia-south1)中,也可能会发生此错误。您可以通过检查数据集位置来验证区域。

解决这些错误时,请考虑以下事项:

  • 服务账号:服务账号必须对用于运行它们的项目拥有 bigquery.jobs.create 权限,并且必须对查询引用的所有表和视图拥有 bigquery.tables.getData 权限。

  • 自定义角色:自定义 IAM 角色必须在相关角色中明确包含 bigquery.jobs.create 权限,并且必须对查询引用的所有表和视图拥有 bigquery.tables.getData 权限。

  • 共享数据集:在单独的项目中使用共享数据集时,您可能仍需要在该项目中拥有 bigquery.jobs.create 权限才能在该数据集中运行查询或作业。

如需授予访问表或视图的权限,请参阅授予对表或视图的访问权限

超出资源数问题

当 BigQuery 没有足够的资源来完成查询时,会出现以下问题。

查询超出 CPU 资源

错误字符串:Query exceeded resource limits

当按需查询使用的 CPU 数量相对于扫描的数据量过多时,便会发生此错误。如需了解如何解决这些问题,请参阅排查超出资源问题

查询超出内存资源

错误字符串:Resources exceeded during query execution: The query could not be executed in the allotted memory

对于 SELECT 语句,如果查询使用的资源过多,就会发生此错误。如需解决此错误,请参阅排查超出资源问题

堆栈空间不足

错误字符串:Out of stack space due to deeply nested query expression during query resolution.

如果查询包含的嵌套函数调用过多,可能会出现此错误。有时,在解析期间,查询的部分内容会转换为函数调用。例如,具有重复串联运算符的表达式(例如 A || B || C || ...)会变为 CONCAT(A, CONCAT(B, CONCAT(C, ...)))

如需解决此错误,请重写查询以减少嵌套量。

查询执行期间超出资源限制

错误字符串:Resources exceeded during query execution: The query could not be executed in the allotted memory. Peak usage: [percentage]% of limit. Top memory consumer(s): ORDER BY operations.

运行 ORDER BY ... LIMIT ... OFFSET ... 查询时可能会发生这种情况。由于实现细节,排序可能会在单个计算单元上进行,如果在应用 LIMITOFFSET 之前需要处理过多行,则计算单元可能会耗尽内存,尤其是在 OFFSET 较大的情况下。

如需解决此错误,请避免在 ORDER BY...LIMIT 查询中使用较大的 OFFSET 值。或者,使用可扩展的 ROW_NUMBER() 窗口函数根据所选顺序分配排名,然后在 WHERE 子句中过滤这些排名。例如:

SELECT ...
FROM (
  SELECT ROW_NUMBER() OVER (ORDER BY ...) AS rn
  FROM ...
)
WHERE rn > @start_index AND rn <= @page_size + @start_index  -- note that row_number() starts with 1

查询超出 shuffle 资源

错误字符串:Resources exceeded during query execution: Your project or organization exceeded the maximum disk and memory limit available for shuffle operations

当查询无法访问足够的 shuffle 资源时,就会发生此错误。

如需解决此错误,请预配更多槽或减少查询处理的数据量。如需详细了解执行此操作的方法,请参阅 shuffle 配额不足

如需详细了解如何解决这些问题,请参阅排查超出资源问题

查询过于复杂

错误字符串:Resources exceeded during query execution: Not enough resources for query planning - too many subqueries or query is too complex

当查询过于复杂时,会发生此错误。造成复杂性的主要原因是:

  • 深度嵌套或反复使用的 WITH 子句。
  • 深度嵌套或反复使用的视图。
  • 重复使用 UNION ALL 运算符

如需解决此错误,请尝试以下方案:

  • 将查询拆分为多个查询,然后使用过程语言以共享状态按顺序运行这些查询。
  • 使用临时表而不是 WITH 子句。
  • 重写查询,以减少引用对象和比较的数量。

您可以使用 INFORMATION_SCHEMA.JOBS 视图中的 query_info.resource_warning 字段,主动监控即将达到复杂性上限的查询。以下示例会返回过去三天内资源使用量较高的查询:

SELECT
  ANY_VALUE(query) AS query,
  MAX(query_info.resource_warning) AS resource_warning
FROM
  <your_project_id>.`region-us`.INFORMATION_SCHEMA.JOBS
WHERE
  creation_time > TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 3 DAY)
  AND query_info.resource_warning IS NOT NULL
GROUP BY
  query_info.query_hashes.normalized_literals
LIMIT
  1000

如需详细了解如何解决这些问题,请参阅排查超出资源问题

排查超出资源数问题

对于查询作业

如需优化查询,请尝试执行以下步骤:

  • 请尝试移除 ORDER BY 子句。
  • 如果查询使用 JOIN,请确保较大的表位于子句左侧。 此外,请确保您的数据不包含重复的联接键。
  • 如果您的查询使用 FLATTEN,请确定它对于您的用例来说是否必要。 如需了解详情,请参阅嵌套重复的数据
  • 如果查询使用 EXACT_COUNT_DISTINCT,请考虑改用 COUNT(DISTINCT)
  • 如果查询使用 COUNT(DISTINCT <value>, <n>) 和较大的 <n> 值,请考虑改用 GROUP BY。如需了解详情,请参阅 COUNT(DISTINCT)
  • 如果查询使用 UNIQUE,请考虑改用 GROUP BY,或子选择内的窗口函数
  • 如果查询使用 LIMIT 子句具体化许多行,请考虑对其他列(例如 ROW_NUMBER())进行过滤,或完全移除 LIMIT 子句以允许并行处理写入操作。
  • 如果查询使用了深层嵌套的视图和 WITH 子句,这可能会导致复杂性呈指数级增长,从而达到相应的限制。
  • 使用临时表而不是 WITH 子句。WITH 子句可能必须多次重新计算,这可能会使查询变得复杂,从而导致速度缓慢。将中间结果持久保留在临时表中,有助于简化复杂性。
  • 请避免使用 UNION ALL 查询。
  • 如果您的查询使用 MATCH_RECOGNIZE,请修改 PARTITION BY 子句以减小分区的大小,或者添加 PARTITION BY 子句(如果不存在)。

如需了解详情,请参阅以下资源:

对于加载作业

如果您要加载 Avro 或 Parquet 文件,请减小文件中的行大小。检查您要加载的文件格式的特定大小限制:

如果您在加载 ORC 文件时遇到此错误,请与支持团队联系

对于 Storage API

错误字符串:Stream memory usage exceeded

在 Storage Read API ReadRows 调用期间,某些具有高内存用量的流可能会收到 RESOURCE_EXHAUSTED 错误,并显示此消息。从宽表或具有复杂架构的表读取数据时,可能会发生这种情况。若要解决此问题,请选择较少要读取的列(使用 selected_fields 参数)或简化表架构来减小结果行大小。

排查连接问题

以下部分介绍了如何排查在尝试与 BigQuery 交互时出现的连接问题:

将 Google DNS 列入许可名单

使用 Google IP Dig 工具将 BigQuery DNS 端点 bigquery.googleapis.com 解析为单个“A”记录 IP。确保防火墙设置中未屏蔽此 IP。

一般来说,我们建议将 Google DNS 名称列入许可名单。https://www.gstatic.com/ipranges/goog.jsonhttps://www.gstatic.com/ipranges/cloud.json 文件中共享的 IP 地址范围经常更改,因此我们建议您改为将 Google DNS 名称列入许可名单。以下是我们建议添加到许可名单中的常见 DNS 名称列表:

  • *.1e100.net
  • *.google.com
  • *.gstatic.com
  • *.googleapis.com
  • *.googleusercontent.com
  • *.appspot.com
  • *.gvt1.com

确定代理或防火墙丢弃数据包

如需识别客户端与 Google Front End (GFE) 之间的所有数据包跳转,请在客户端机器上运行 traceroute 命令,该命令可以突出显示丢弃面向 GFE 的数据包的服务器。以下是 traceroute 命令示例:

traceroute -T -p 443 bigquery.googleapis.com

如果问题与特定 IP 地址相关,还可以识别特定 GFE IP 地址的数据包跳数:

traceroute -T -p 443 142.250.178.138

如果存在 Google 端超时问题,您会看到请求一直到达 GFE。

如果您发现数据包从未到达 GFE,请与您的网络管理员联系,以解决此问题。

生成 PCAP 文件并分析防火墙或代理

生成数据包捕获文件 (PCAP) 并分析该文件,以确保防火墙或代理未过滤掉发往 Google IP 的数据包,并允许数据包到达 GFE。

以下是可以使用 tcpdump 工具运行的示例命令:

tcpdump -s 0 -w debug.pcap -K -n host bigquery.googleapis.com

针对间歇性连接问题设置重试

在某些情况下,GFE 负载均衡器可能会丢弃来自客户端 IP 的连接,例如,如果它检测到 DDoS 流量模式,或者如果负载均衡器实例正在缩减,这可能会导致端点 IP 被回收。如果 GFE 负载均衡器断开连接,客户端需要捕获超时请求并重试向 DNS 端点发送请求。请确保在请求最终成功之前不使用相同的 IP 地址,因为该 IP 地址可能已更改。

如果您发现 Google 端持续超时且重试不起作用的问题,请与 Cloud Customer Care 联系,并确保附上通过运行数据包捕获工具(如 tcpdump)生成的新 PCAP 文件。

后续步骤