可靠性:查询数据

本文档介绍如何使用 BigQuery 构建可靠解决方案,以及如何在 BigQuery 环境中可靠地查询数据。

了解槽

BigQuery 在运行查询作业时,会将提交的声明式 SQL 语句转换为执行图。此执行图会分解为一系列查询阶段,而这些阶段本身由更细化的多组执行步骤构成。BigQuery 会使用高度分布式的并行架构来运行这些查询,而这些阶段则会建立许多潜在工作器可能并行执行的工作单元模型。这些工作器的资源称为槽

简单来说,BigQuery 槽是 BigQuery 执行 SQL 查询时使用的虚拟 CPU。如需详细了解槽及其工作原理,请参阅了解槽

通过在两个单独的可用区提供冗余槽容量,BigQuery 可为查询实现 99.99% 的服务等级协议 (SLA)。这种分布可保护客户免受可用区故障影响。

用于运行查询的计算资源是以按需价格或固定费率价格模型购买的。在按需模型中,计算资源根据提交的查询处理的字节数收费。在固定费率模型下,您将购买专用数量的查询处理容量,该容量可提供稳定的费用模型。

按需分析模型

使用 BigQuery 的按需价格模型时,您只需根据提交的查询处理的字节数量(也称为“读取的字节数”)付费。使用 BigQuery 按需价格模型的项目可以访问槽的默认容量,这通常足够了,并且受每个项目槽配额的约束。

固定费率槽模型

如果客户更希望使用稳定的查询费用,而不是付费使用按需价格模型,则应考虑固定费率价格模型。注册固定费率价格方案时,您将以 BigQuery 槽为单位购买专用的查询处理能力。您的查询会使用此容量,而您无需按处理的字节数付费。

使用搞定费率结构,客户可以按不同承诺期限(每年、每月或无承诺)购买槽、优先将槽用于具有槽预留的指定项目或文件夹,以及在多个预留之间共享空闲槽。如需了解详情,请参阅预留简介

固定费率模型明确设置了文件夹或项目可用的最大槽资源数量,因此购买太少的槽可能会影响查询的性能,而购买太多槽可能会造成空闲处理容量,导致资源利用率过低和不必要的费用。

固定费率槽模型的注意事项

虽然费用考虑通常是选择按需模型和固定费率模型的最大驱动因素,但此决策也会影响可靠性。例如,按需价格模型与固定费率模型的扩缩能力可能会有所不同,前者在峰值负载期间最少可以为每个项目提供 2000 个可用槽,而后者可配置多达数十万个槽。项目使用的槽数取决于查询复杂性、扫描的数据量、用户定义的函数 (UDF) 等特殊函数以及提交的并发查询的数量。但是,面向按需客户提供的 2000 个槽通常足以满足使用 BigQuery 开始的新用户。如需详细了解如何在 BigQuery 按需价格和固定费率模型之间进行选择,请参阅在 BigQuery 按需价格和固定价格之间进行选择

BigQuery 的 99.99% 可用性 SLA 同时适用于按需价格和固定费率模型,但槽资源量仅在固定费率模型下保证,因为按需模型使用共享槽资源池。请注意,在购买和预配预留槽之前,BigQuery 不保证其可用性。因此,Google 建议您不要依赖为业务关键型工作负载即时获取预留槽。槽请求数越大,要求提前预配槽资源的可能性就越大。

您也可以在组织或项目中组合使用按需模型和固定费率模型,以更好地满足您的需求。这可通过 BigQuery 的 BigQuery 预留概念来实现。一个较好的示例是,为美国多区域的生产数据集使用固定费率预留,为备用区域的较小开发数据集使用按需容量。

预留

借助 BigQuery 预留,您可以自定义整个组织中槽容量的分配方式,进而根据工作负载确定资源的优先级。例如,您可以为生产工作负载创建名为 prod 的预留,以及为测试创建一个名为 test 的单独预留。这样,您的训练作业就不会因生产工作负载所需的资源而展开竞争。预留根据分配的项目、文件夹或组织指定槽资源的优先级。除非被替换,否则资源层次结构中的每个级别都会继承上一级别的分配。换句话说,项目继承其父文件夹的分配,而文件夹则继承其组织的分配。

默认情况下,BigQuery 预留也会在其他预留之间共享空闲槽资源,从而优化资源利用率。这样,在未完全利用生产预留的期间,诸如开发/测试环境之类的非优先工作负载可以获得更好的查询性能。如果开发/测试工作负载使用生产预留中未使用的槽,并且生产预留现在得到充分利用,则 BigQuery 槽调度器将智能地从运行中的开发/测试查询中拉取槽资源,以将其提供给生产预留。开发/测试查询将继续运行,但速度会变慢,因为它们使用的计算资源变少了。

根据分析需求的性质,通常您可以根据业务部门、功能(生产与开发/测试)或应用类型(商业智能信息中心与计划查询/作业与用户的临时查询)来分离工作负载,从而在环境中创建多个 BigQuery 预留。

请注意,空闲槽仅在单个 BigQuery 管理项目内创建的预留中共享。

调整预留的大小

通常,最好通过 BigQuery 管理员资源图表Cloud Monitoring 信息中心监控当前和历史 BigQuery 槽用量,来准确调整预留大小。管理员资源图表可提供实时数据和过去 14 天的历史数据,包括组织、文件夹、项目、预留、用户或作业级层的槽用量、作业并发和作业性能的相关详细信息。

优化作业可靠性

可以提交两种类型的查询来分析数据:

  • 交互式查询:提交的交互式查询会被立即分派执行。
  • 批量查询:提交的批量查询会排入队列,并在有足够的槽资源可用时立即开始运行。如果 BigQuery 没有在 24 小时内启动查询,则会将作业优先级更改为交互式并立即分派查询。

交互式查询和批量查询均使用相同的槽资源。实际上,BigQuery 调度器启动批量查询后,交互式查询或批量查询之间的优先级没有区别。但是,交互式查询和批量查询对查询限制和配额的影响确实不同。交互式查询会计入并发查询速率限制,而批量查询则不会。

如果达到并发查询限制,则交互式查询将失败,并显示 quotaExceeded 错误。此配额可以起到保护作用,因此只要可用槽尚未用完,您通常都可以联系客户服务销售提高此配额。但是,高度并发运行的查询会降低每个查询的总体计算资源可用性,因此可能导致资源争用并降低每个查询的处理吞吐量。因此,您不应将并发查询配额超出槽资源饱和点。如果遇到并发查询错误,您可以使用指数退避算法重试查询,以避免对查询作业延迟时间产生负面影响。

减少环境中并发查询数量的选项包括:

  • 试运行模式下运行查询,此模式会估算读取的字节数,但不会实际处理查询。
  • 在实验或探索数据时,您可以使用 BigQuery 的表预览功能预览表数据,而不是运行查询。
  • 使用缓存的查询结果。所有查询结果(包括交互式查询和批量查询)都会在临时表中缓存大约 24 小时,但有一些例外情况。虽然运行缓存的查询仍会计入并发查询限制,但使用缓存结果的查询速度明显更快,因为 BigQuery 不需要计算结果集。
  • 使用 BI Engine,它是 BigQuery 的高速内存分析服务。BI Engine 让您可以使用 Google Data StudioSQL 界面等工具构建交互式信息中心和报告,并为存储在 BigQuery 中的数据提供更高的并发性。这对于大量小型查询尤其有效。

与查询并发和作业性能相关的其他注意事项是作业隔离和错开作业。通过在各项目或预留之间按应用使用场景隔离查询作业,可以减少相邻用户争用问题,即某个查询消耗大量资源,从而对其他查询的性能产生负面影响。这也降低了遇到按项目并发查询限制的可能性。

错开作业或按顺序提交多个作业(而不是同时提交多个作业)也可能会有益于整体性能和降低错误率。例如,假设有一组五个复杂的作业。假设同时运行这五个查询将消耗大量槽并在一小时内完成执行。按顺序提交相同的五个作业可能仍会在一小时内执行,但将释放槽资源以供其他查询使用,并降低遇到并发查询限制的可能性。

BigQuery 使用公平调度机制在项目或预留内的竞争查询之间分配资源。这意味着所有查询都可以随时平等地访问所有可用槽,并且系统可以自动根据每个活跃查询的容量需求变化在这些查询之间动态地重新分配容量。因此,在同一项目或预留中运行业务关键型生产和开发/测试查询可能并不理想,因为每个查询都具有对槽的访问权限,因此非关键查询可能会影响运行中的关键查询的性能。最佳做法是在查询执行之前确定查询的优先级。

可靠性优化的 DML 注意事项

BigQuery 数据操纵语言 (DML) 语句让您可以更新、插入和删除 BigQuery 表中的数据,并且在可靠性具有它们自己的准则。

  • BigQuery 是完全原子化的,因此每个 DML 语句都会启动一个隐式事务,这表示在每个 DML 语句成功结束时,系统会自动提交该语句所做的更改。
  • DML UPDATE、DELETE 或 MERGE 语句不能用于具有活跃流式缓冲区的表。尝试这样做会导致查询失败。
  • DML INSERT、UPDATE、DELETE 和 MERGE 语句没有并发配额限制。但是,一旦达到并发作业的特定阈值,新作业就会排入队列,进入待处理状态。
  • 如果在同一表上并发运行多个变更型 DML 语句,BigQuery 会确定 DML 是否可以更改相同的后端文件,以及只允许一个 DML 继续,同时重试其他 DML(最多三次)。如果后续三次 DML 重试失败,则 DML 语句将因其尝试进行的更改发生冲突而失败。
  • 虽然 BigQuery 完全支持 DML UPDATE、DELETE 和 MERGE 操作,但它不是事务型 OLTP 样式数据库。

最佳实践是避免提交大量单独的 DML 行更新或插入,而是尽可能将 DML 操作组合在一起。

可靠性优化的 UDF 注意事项

BigQuery 用户定义的函数 (UDF) 是通过 SQL 表达式或 JavaScript 代码创建的永久性函数或临时性函数,可根据提供的代码执行返回结果。UDF 在可靠性方面有自己的准则。

  • 与标准 SQL 查询相比,UDF 通常会消耗更多的槽资源,并且可能会影响作业性能。如果函数可以使用 SQL 表示,则通常最好将代码作为标准 SQL 查询作业运行。
  • JavaScript UDF 可能超时,导致查询无法完成。超时可能只有短短 5 分钟,但因多种因素而有所不同,包括函数占用的用户 CPU 时间以及 JavaScript 函数的输入和输出大小。
  • UDF 有自己的配额和并发查询限制。如需了解详情,请参阅 UDF 限制

管理配额和限制

如前所述,查询作业受许多限制和配额的约束。这些限制因查询类型以及其他因素而异,但查询或脚本执行时间的上限为 6 小时。此限制无法更改。在某些情况下,可以重试查询。发生这种情况时,重试的查询可额外运行六小时,最多可重试三次。

监控查询作业

监控 BigQuery 作业对于运行可靠应用至关重要。可以通过 BigQuery 管理员资源图表Cloud Monitoring 信息中心或 BigQuery 的 INFORMATION_Schema 表来完成监控。
借助 BigQuery 管理员资源图表和 Cloud Monitoring 信息中心,您可以原生监控查询的字节数、执行的并发查询数、槽用量、查询延迟时间等。而 INFORMATION_SCHEMA 表提供有关作业类型、特定错误消息、缓存速率、作业复杂性等的其他元数据。利用 INFORMATION_SCHEMA 表可提供其他自定义层,例如以下查询可提供最新查询列表,这些查询处于待处理或当前正在运行状态,按创建后的时长排序:

SELECT
    creation_time,
    project_id,
    user_email,
    job_id,
    job_type,
    priority,
    state,
    TIMESTAMP_DIFF(CURRENT_TIMESTAMP(), start_time,second) as running_time_sec
 FROM
   region-us.INFORMATION_SCHEMA.JOBS_BY_PROJECT
 WHERE
    creation_time BETWEEN TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 DAY) AND CURRENT_TIMESTAMP()
    AND state != "DONE"
ORDER BY
    running_time_sec DESC

查询数据的使用场景

实时分析

在此使用场景中,流式数据流入实时 BI 信息中心,供大量运行交互式查询的用户使用。

在此使用场景中,您应该使用单独的项目或预留,将 BI 信息中心查询与其他通用查询隔离开来,以避免 BI 信息中心成为争用资源的相邻用户以及影响其他通用查询作业的性能。此外,应通过查看 INFORMATION_SCHEMA 表来实现监控运行中查询、费用高昂的查询和显示 BigQuery 反模型的 SQL 查询,并进行更正以避免不必要的支出和查询延迟时间。

如果针对 BI 信息中心提交了大量并发查询作业,或者查询延迟时间存在问题,请考虑利用 BI Engine

请考虑创建自定义费用控制限制,以限制每个用户或每个表每天可处理的数据量。

批量数据处理

在此使用场景中,系统会处理复杂的每晚批量作业,对一整天的数据进行全面分析,并将其与其他数据源联接以丰富数据。

与实时用例的指南类似,建议通过使用单独的项目或预留来将这些复杂的批量查询与其他通用查询隔离开来,以避免这些作业成为争用资源的相邻用户以及影响其他查询作业的性能。此外,应通过 INFORMATION_SCHEMA 表来监控长时间运行的查询、费用高昂的查询和显示 BigQuery 反模型的 SQL 查询,并进行更正以避免不必要的支出和查询延迟时间。

请考虑在 Cloud Monitoring 中创建提醒,以针对槽可用性低、查询时间长、扫描字节数多等问题发出提醒,进而针对性能不佳的作业发出提醒。

后续步骤