估算和控制费用

本页面介绍了在 BigQuery 中估算和控制费用的最佳实践。

BigQuery 中的主要费用是计算费用(用于查询处理)和存储费用(用于存储在 BigQuery 中的数据)。BigQuery 为查询处理提供了两种类型的价格模式:按需价格和基于容量的价格。每种模式都提供不同的费用控制最佳实践。对于存储在 BigQuery 中的数据,费用取决于为每个数据集配置的存储空间结算模式

了解 BigQuery 的计算价格

BigQuery 的计算价格存在细微差异,这些差异会影响容量规划和费用控制。

价格模式

对于 BigQuery 中的按需计算,您需要为 BigQuery 查询按 TiB 付费。

或者,对于 BigQuery 中的容量计算,您需要为用于处理查询的计算资源()付费。如需使用此模型,您需要为槽配置预留

预留具有以下特征:

  • 它们以槽池的形式分配,可让您以适合组织的方式管理容量并隔离工作负载。
  • 它们必须位于一个管理项目中,并受配额和限制约束。

容量价格模式提供多种版本,所有版本均提供按槽时间(小时)计费的随用随付选项。企业版和企业 Plus 版还提供可选的 1 年期或 3 年期槽承诺,可比随用随付费率节省费用。

您还可以使用随用随付选项设置自动扩缩预留。详情请参阅以下内容:

限制每种模式的费用

使用按需价格模式时,限制费用的唯一方法是配置项目级或用户级每日配额。不过,这些配额会执行强制限额,以防止用户运行超出配额限制的查询。如需设置配额,请参阅创建自定义查询配额

借助槽预留使用容量价格模式时,需要指定可用于预留的槽数上限。您还可以购买在承诺期限内提供折扣价格的槽承诺。

您可以将预留的基准设置为 0,并将上限设置为满足工作负载需求的设置,从而完全按需使用相应版本。BigQuery 会自动扩容到您的工作负载所需的槽数,绝不会超过您设置的上限。如需了解详情,请参阅使用预留管理工作负载

控制查询费用

如需控制单个查询的费用,我们建议您先遵循优化查询计算优化存储方面的最佳实践。

以下部分概述了您可以用于进一步控制查询费用的其他最佳实践。

创建自定义查询配额

最佳实践:使用自定义每日查询配额来限制每日处理的数据量。

您可以设置自定义配额以指定每个项目或每个用户在每日可处理的数据量限额,从而管理费用。达到配额后,用户将无法运行查询。

如需设置自定义配额,您需要具备特定角色或权限。如需了解要设置的配额,请参阅配额和限制

如需了解详情,请参阅限制每种价格模式的费用

在运行查询之前检查估算费用

最佳做法:在运行查询前,先进行预览以估算相关费用。

使用按需价格模式时,系统会根据读取的字节数收取查询费用。如需在运行查询之前估算费用,请使用以下方法:

使用查询验证器

在 Google Cloud 控制台中输入查询时,查询验证器会验证查询语法并估算读取的字节数。有了此估算值,您便可在价格计算器中计算查询费用。

  • 如果查询无效,则查询验证器会显示错误消息。例如:

    Not found: Table myProject:myDataset.myTable was not found in location US

  • 如果查询有效,则查询验证器会估算处理查询所需的字节数。例如:

    This query will process 623.1 KiB when run.

执行试运行

如需执行试运行,请执行以下操作:

控制台

  1. 转到 BigQuery 页面。

    转到 BigQuery

  2. 在查询编辑器中输入查询。

    如果查询有效,则会自动显示一个对勾标记以及查询将处理的数据量。如果查询无效,则会显示一个感叹号,并会显示错误消息。

bq

使用 --dry_run 标志输入如下所示的查询。

bq query \
--use_legacy_sql=false \
--dry_run \
'SELECT
   COUNTRY,
   AIRPORT,
   IATA
 FROM
   `project_id`.dataset.airports
 LIMIT
   1000'
 

对于有效查询,该命令会生成以下响应:

Query successfully validated. Assuming the tables are not modified,
running this query will process 10918 bytes of data.

API

如需使用 API 执行试运行,请提交一项查询作业,并在 JobConfiguration 类型中将 dryRun 设置为 true

Go

试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Go 设置说明进行操作。 如需了解详情,请参阅 BigQuery Go API 参考文档

如需向 BigQuery 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/bigquery"
)

// queryDryRun demonstrates issuing a dry run query to validate query structure and
// provide an estimate of the bytes scanned.
func queryDryRun(w io.Writer, projectID string) error {
	// projectID := "my-project-id"
	ctx := context.Background()
	client, err := bigquery.NewClient(ctx, projectID)
	if err != nil {
		return fmt.Errorf("bigquery.NewClient: %v", err)
	}
	defer client.Close()

	q := client.Query(`
	SELECT
		name,
		COUNT(*) as name_count
	FROM ` + "`bigquery-public-data.usa_names.usa_1910_2013`" + `
	WHERE state = 'WA'
	GROUP BY name`)
	q.DryRun = true
	// Location must match that of the dataset(s) referenced in the query.
	q.Location = "US"

	job, err := q.Run(ctx)
	if err != nil {
		return err
	}
	// Dry run is not asynchronous, so get the latest status and statistics.
	status := job.LastStatus()
	if err := status.Err(); err != nil {
		return err
	}
	fmt.Fprintf(w, "This query will process %d bytes\n", status.Statistics.TotalBytesProcessed)
	return nil
}

Java

试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Java 设置说明进行操作。 如需了解详情,请参阅 BigQuery Java API 参考文档

如需向 BigQuery 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.Job;
import com.google.cloud.bigquery.JobInfo;
import com.google.cloud.bigquery.JobStatistics;
import com.google.cloud.bigquery.QueryJobConfiguration;

// Sample to run dry query on the table
public class QueryDryRun {

  public static void runQueryDryRun() {
    String query =
        "SELECT name, COUNT(*) as name_count "
            + "FROM `bigquery-public-data.usa_names.usa_1910_2013` "
            + "WHERE state = 'WA' "
            + "GROUP BY name";
    queryDryRun(query);
  }

  public static void queryDryRun(String query) {
    try {
      // Initialize client that will be used to send requests. This client only needs to be created
      // once, and can be reused for multiple requests.
      BigQuery bigquery = BigQueryOptions.getDefaultInstance().getService();

      QueryJobConfiguration queryConfig =
          QueryJobConfiguration.newBuilder(query).setDryRun(true).setUseQueryCache(false).build();

      Job job = bigquery.create(JobInfo.of(queryConfig));
      JobStatistics.QueryStatistics statistics = job.getStatistics();

      System.out.println(
          "Query dry run performed successfully." + statistics.getTotalBytesProcessed());
    } catch (BigQueryException e) {
      System.out.println("Query not performed \n" + e.toString());
    }
  }
}

Node.js

试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Node.js 设置说明进行操作。 如需了解详情,请参阅 BigQuery Node.js API 参考文档

如需向 BigQuery 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

// Import the Google Cloud client library
const {BigQuery} = require('@google-cloud/bigquery');
const bigquery = new BigQuery();

async function queryDryRun() {
  // Runs a dry query of the U.S. given names dataset for the state of Texas.

  const query = `SELECT name
    FROM \`bigquery-public-data.usa_names.usa_1910_2013\`
    WHERE state = 'TX'
    LIMIT 100`;

  // For all options, see https://cloud.google.com/bigquery/docs/reference/rest/v2/jobs/query
  const options = {
    query: query,
    // Location must match that of the dataset(s) referenced in the query.
    location: 'US',
    dryRun: true,
  };

  // Run the query as a job
  const [job] = await bigquery.createQueryJob(options);

  // Print the status and statistics
  console.log('Status:');
  console.log(job.metadata.status);
  console.log('\nJob Statistics:');
  console.log(job.metadata.statistics);
}

PHP

试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 PHP 设置说明进行操作。 如需了解详情,请参阅 BigQuery PHP API 参考文档

如需向 BigQuery 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

use Google\Cloud\BigQuery\BigQueryClient;

/** Uncomment and populate these variables in your code */
// $projectId = 'The Google project ID';
// $query = 'SELECT id, view_count FROM `bigquery-public-data.stackoverflow.posts_questions`';

// Construct a BigQuery client object.
$bigQuery = new BigQueryClient([
    'projectId' => $projectId,
]);

// Set job configs
$jobConfig = $bigQuery->query($query);
$jobConfig->useQueryCache(false);
$jobConfig->dryRun(true);

// Extract query results
$queryJob = $bigQuery->startJob($jobConfig);
$info = $queryJob->info();

printf('This query will process %s bytes' . PHP_EOL, $info['statistics']['totalBytesProcessed']);

Python

QueryJobConfig.dry_run 属性设置为 True。如果提供了试运行查询配置,Client.query() 将始终返回已完成的 QueryJob

试用此示例之前,请按照 BigQuery 快速入门:使用客户端库中的 Python 设置说明进行操作。 如需了解详情,请参阅 BigQuery Python API 参考文档

如需向 BigQuery 进行身份验证,请设置应用默认凭据。 如需了解详情,请参阅为客户端库设置身份验证

from google.cloud import bigquery

# Construct a BigQuery client object.
client = bigquery.Client()

job_config = bigquery.QueryJobConfig(dry_run=True, use_query_cache=False)

# Start the query, passing in the extra configuration.
query_job = client.query(
    (
        "SELECT name, COUNT(*) as name_count "
        "FROM `bigquery-public-data.usa_names.usa_1910_2013` "
        "WHERE state = 'WA' "
        "GROUP BY name"
    ),
    job_config=job_config,
)  # Make an API request.

# A dry run query completes immediately.
print("This query will process {} bytes.".format(query_job.total_bytes_processed))

估算查询费用

使用按需价格模式时,您可以通过计算所处理的字节数来估算运行查询的费用。

按需查询大小计算

如需计算各种类型的查询处理的字节数,请参阅以下部分:

避免运行查询来探索表数据

最佳做法:不要运行查询来探索或预览表数据。

如果您要进行数据实验或探索数据,可以使用表预览选项来查看数据,这种方式是免费的而且不会影响配额。

BigQuery 支持以下数据预览选项:

  • 在 Google Cloud 控制台中的表详情页面上,点击预览标签页以对数据进行采样。
  • 在 bp 命令行工具中,使用 bq head 命令并指定要预览的行数。
  • 在 API 中,使用 tabledata.list 从一组指定的行中检索表数据。
  • 避免在非聚簇表中使用 LIMIT。对于非聚簇表,LIMIT 子句不会降低计算费用。

限制每个查询的结算字节数

最佳实践:在使用按需价格模式时,使用结算字节数上限设置来限制查询费用。

您可以使用结算字节数上限设置来限制对查询结算的字节数。设置结算字节数上限时,将在执行查询之前估算查询将读取的字节数。如果估算的字节数超过了限制,则查询会失败,但不会产生费用。

对于聚簇表,对查询计费的字节数估算值为上限,可能会高于运行查询后实际计费的字节数。因此,在某些情况下,如果设置了结算字节数上限,则对聚簇表运行的查询可能会失败,即使实际结算的字节数不会超过结算字节数上限设置也不例外。

如果查询因结算字节数上限设置而失败,将返回类似如下的错误:

Error: Query exceeded limit for bytes billed: 1000000. 10485760 or higher required.

如需设置结算字节数上限,请按如下所述操作:

控制台

  1. 查询编辑器中,点击更多 > 查询设置 > 高级选项
  2. 结算字节数上限字段中,输入一个整数。
  3. 点击保存

bq

使用带有 --maximum_bytes_billed 标志的 bq query 命令。

  bq query --maximum_bytes_billed=1000000 \
  --use_legacy_sql=false \
  'SELECT
     word
   FROM
     `bigquery-public-data`.samples.shakespeare'

API

JobConfigurationQueryQueryRequest 中设置 maximumBytesBilled 属性。

避免在非聚簇表中使用 LIMIT

最佳做法:对于非聚簇表,请勿使用 LIMIT 子句控制费用。

对于非聚簇表,对查询应用 LIMIT 子句不会影响读取的数据量。您需要支付读取查询所指示整个表中的所有字节而产生的费用,即使该查询仅返回子集。对于聚簇表,LIMIT 子句可以减少扫描的字节数,因为扫描足够多的块来获取结果后会停止扫描。您只需为扫描的字节数付费。

分阶段将查询结果具体化

最佳做法:如果可能,请分阶段将查询结果具体化。

如果您创建了一个大型的多阶段查询,则每次运行该查询时,BigQuery 都会读取查询所需的所有数据。这样,您就需要支付查询在每次运行时读取的所有数据所产生的费用。

因此,更好的做法是将查询分为多个阶段,并在每个阶段中通过将查询结果写入一个目标表来将这些结果具体化。 查询较小的目标表可减少数据读取量并降低费用。存储具体化结果的费用远低于处理大量数据的费用。

控制工作负载费用

本部分介绍了在工作负载中控制费用的最佳实践。工作负载是一组相关查询。例如,工作负载可以是每日运行的数据转换流水线、由一组业务分析师运行的一组信息中心,或由一组数据科学家运行的若干个临时查询。

使用 Google Cloud 价格计算器

最佳实践:使用Google Cloud 价格计算器根据预计用量来为 BigQuery 创建总体的每月估算费用。然后,您可以将此估算值与实际费用进行比较,以确定需要优化的方面。

按需

使用按需价格模式时,如需在Google Cloud 价格计算器中估算费用,请按照以下步骤操作:

  1. 打开Google Cloud 价格计算器
  2. 点击添加到估算
  3. 选择 BigQuery。
  4. 服务类型字段中,选择“按需”。
  5. 选择将运行查询的位置。
  6. 对于 Amount of data queried(查询的数据量),输入通过试运行或查询验证器估算的读取字节数。
  7. 输入 Active storage(活跃存储空间)、Long-term storage(长期存储空间)、Streaming inserts(流式插入)和 Streaming reads(流式读取)的存储空间用量的估算值。 您只需要估算物理存储空间或逻辑存储空间,具体取决于数据集存储结算模式
  8. 估算结果会显示在费用详情面板中。如需详细了解估算费用,请点击打开详情视图。您还可以下载和分享费用估算值。

如需了解详情,请参阅按需价格

版本

将基于容量的价格模式与 BigQuery 版本搭配使用时,如需在Google Cloud 价格计算器中估算费用,请按照以下步骤操作:

  1. 打开Google Cloud 价格计算器
  2. 点击添加到估算
  3. 选择 BigQuery。
  4. 服务类型字段中,选择“版本”。
  5. 选择槽的使用位置。
  6. 选择您的版本
  7. 选择槽数上限基准槽数、可选的承诺Estimated utilization of autoscaling(估算的自动扩缩利用率)。
  8. 选择数据的存储位置。
  9. 输入 Active storage(活跃存储空间)、Long-term storage(长期存储空间)、Streaming inserts(流式插入)和 Streaming reads(流式读取)的存储空间用量的估算值。 您只需要估算物理存储空间或逻辑存储空间,具体取决于数据集存储结算模式
  10. 估算结果会显示在费用详情面板中。如需详细了解估算费用,请点击打开详情视图。您还可以下载和分享费用估算值。

如需了解详情,请参阅基于容量的价格

使用预留和承诺

最佳实践:使用 BigQuery 预留和承诺来控制费用。

如需了解详情,请参阅限制每种价格模式的费用

使用槽 Estimator

最佳实践:使用槽 Estimator 估算工作负载所需的槽数。

BigQuery 槽 Estimator 可帮助您根据历史性能指标管理槽容量。

此外,使用按需价格模式的客户在改用基于容量的价格时,可以查看针对性能类似的承诺和自动扩缩预留的容量调整建议。

取消不必要的长时间运行的作业

如需释放容量,请检查长时间运行的作业,确保它们应该继续运行。如果不应该继续运行,请取消它们。

使用信息中心查看费用

最佳实践:创建信息中心来分析 Cloud Billing 数据,以便可以监控和调整 BigQuery 使用量。

您可以导出结算数据到 BigQuery,并在 Looker 数据洞察等工具中直观呈现这些数据。如需查看有关如何创建结算信息中心的教程,请参阅使用 BigQuery 和 Looker Studio 直观呈现 Google Cloud 结算信息

使用结算预算和提醒

最佳实践:使用 Cloud Billing 预算在一个位置监控 BigQuery 费用。

借助 Cloud Billing 预算,您可以按照计划费用来跟踪实际费用。设置预算金额后,您可以设置预算提醒阈值规则,用于触发电子邮件通知。预算提醒电子邮件有助于您随时了解 BigQuery 支出相对于预算的变化情况。

控制存储费用

可遵循以下最佳实践来优化 BigQuery 存储费用。您还可以优化存储以提升查询性能

使用长期存储

最佳实践:使用长期存储价格来降低较旧数据的费用。

将数据加载到 BigQuery 存储中后,数据会按照 BigQuery 存储价格计费。对于较旧的数据,您可以自动利用 BigQuery 长期存储价格。

如果您的某个表连续 90 天未曾修改,则该表的存储价格会自动下降 50%。如果您有一个分区表,则每一个分区都会被视为单独的个体来判断是否适用长期存储价格,并遵循与非分区表相同的规则。

配置存储空间结算模式

最佳实践:根据您的使用模式优化存储空间结算模式。

BigQuery 支持按逻辑(未压缩)字节数或物理(已压缩)字节数或者两者的组合来结算存储空间费用。为每个数据集配置的存储空间结算模式决定了您的存储价格,但不会影响查询性能。

您可以使用 INFORMATION_SCHEMA 视图根据您的使用模式确定最合适的存储空间结算模式。

避免覆盖表

最佳实践:使用物理存储空间结算模式时,请避免反复覆盖表。

当您覆盖表时(例如,在批量加载作业中使用 --replace 参数或使用 TRUNCATE TABLE SQL 语句),系统会在时间旅行和故障安全窗口期间保留被替换的数据。如果您经常覆盖表,则会产生额外的存储空间费用。

您可以改为在加载作业中使用 WRITE_APPEND 参数、使用 MERGE SQL 语句或使用 Storage Write API,从而以增量方式将数据加载到表中。

缩短时间旅行窗口

最佳实践:根据您的要求,您可以缩短时间旅行窗口。

时间旅行窗口减少为小于默认值 7 天,可缩短在表中删除或更改的数据的保留期限。只有在使用物理(已压缩)存储空间计费模式时,您才需要为时间旅行存储空间付费。

时间旅行窗口在数据集级层设置。 您还可以使用配置设置为新数据集设置默认时间旅行窗口。

使用目标表的表过期时间

最佳做法:如果要将大量查询结果写入目标表,请使用默认表过期时间移除不再需要的数据。

将大型结果集保留在 BigQuery 存储空间中会产生费用。如果您不需要永久访问这些结果,请使用默认表过期时间来让系统自动为您删除数据。

将数据归档到 Cloud Storage

最佳做法:考虑将数据归档到 Cloud Storage 中。

您可以根据业务对归档的需求将数据从 BigQuery 迁移到 Cloud Storage。最佳实践是在从 BigQuery 导出数据之前考虑长期存储价格物理存储空间结算模式

后续步骤