估算存储和查询费用

对于按需查询,我们会根据读取的字节数收费。如需了解当前的按需查询价格,请参阅价格页面。

要在运行查询之前估算费用,请使用以下方式:

  • 在 Cloud Console 中查询验证器
  • bq 命令行工具中的 --dry_run 标志
  • dryRun 参数(使用 API 提交查询作业时)
  • Google Cloud 价格计算器
  • 客户端库

估算查询费用

估算查询费用的方法如下:

控制台

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

查询验证器

bq

bq 命令行工具中运行查询时,您可以使用 --dry_run 标志估算读取的字节数。有了此估算值,您便可在价格计算器中计算查询费用。

使用 --dry_run 标志的 bq 工具查询如下所示:

bq query \
--use_legacy_sql=false \
--dry_run \
'SELECT
  column1,
  column2,
  column3
FROM
  `project_id.dataset.table`
LIMIT
  1000'

运行此命令后,响应会包含估算的读取字节数:Query successfully validated. Assuming the tables are not modified, running this query will process 10918 bytes of data.

API

要使用 API 执行试运行,请提交一项查询作业,并将 dryRun 设置为 true

Go

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

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 != nil {
		return err
	}
	fmt.Fprintf(w, "This query will process %d bytes\n", status.Statistics.TotalBytesProcessed)
	return nil
}

Java

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

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 参考文档

// 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);
}

Python

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

要使用 Python 客户端库执行试运行,请将 QueryJobConfig.dry_run 属性设置为 True。如果提供了试运行查询配置,Client.query() 将始终返回完成的 QueryJob
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))

使用 Google Cloud 价格计算器估算查询费用

如需使用 Google Cloud 价格计算器估算按需查询费用,请输入查询处理的字节数(以 B、KB、MB、GB、TB 或 PB 为单位)。 如果您的查询处理的数据量不足 1 TB,估算结果就是 $0,因为 BigQuery 每月免费提供 1 TB 的按需查询处理配额。

价格计算器

使用价格计算器估算查询费用的方法如下:

  1. 打开 Google Cloud 价格计算器
  2. 点击“BigQuery”。
  3. 点击按需标签页。
  4. 对于表名称,输入表的名称。例如 airports
  5. 对于存储价格 (Storage Pricing),在存储字段中输入 0
  6. 对于查询价格 (Query Pricing),输入通过试运行或查询验证器估算的读取字节数。计算器
  7. 点击添加到估算值 (Add To Estimate)。
  8. 估算值会显示在右侧。请注意,您可以保存估算值,也可以通过电子邮件发送估算值。按需计算器

在本例中,查询读取的字节数少于免费层级提供的 1 TB 按需处理配额。因此,估算费用为 $0。

在价格计算器中包含固定费率价格

如果您的结算帐号采用了固定费率价格,您可以点击固定费率标签页,选择您的固定费率方案,随后在估算设置中添加您的存储费用。

固定费率计算器

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

使用 Google Cloud 价格计算器估算存储费用

如需使用 Google Cloud 价格计算器估算存储费用,请输入存储的字节数(以 B、KB、MB、GB、TB 或 PB 为单位)。 BigQuery 每月提供 10 GB 的存储空间。

使用价格计算器估算存储费用的方法如下:

  1. 打开 Google Cloud 价格计算器
  2. 点击“BigQuery”。
  3. 点击按需标签页。
  4. 对于表名称,输入表的名称。例如 airports
  5. 对于存储价格 (Storage Pricing),在存储字段中输入 100。将计量单位设置保留为 GB
  6. 点击添加到估算 (Add To Estimate)。
  7. 估算值会显示在右侧。请注意,您可以保存估算值,也可以通过电子邮件发送估算值。价格计算器

查询大小计算

本部分介绍如何使用按需结算模式计算各种类型的查询处理的字节数。

DML 语句

如果使用按需结算,BigQuery 会根据语句处理的字节数收取数据操纵语言 (DML) 语句的费用。

对于非分区表,处理的字节数按如下方式计算:

DML 语句 处理的字节数
INSERT 执行查询时对扫描的表中被引用的所有列处理的总字节数。
UPDATE 执行查询时扫描的表中被引用的所有列包含的总字节数
UPDATE 开始时所更新的表中所有列的总字节数之和。
DELETE 执行查询时扫描的表中被引用的所有列包含的总字节数
DELETE 开始时所修改的表中所有列的总字节数之和。
MERGE 如果 MERGE 语句中仅包含 INSERT 子句,您需要支付的费用取决于执行查询时对扫描的所有表中被引用的所有列处理的总字节数。
如果 MERGE 语句中包含 UPDATEDELETE 子句,则您需要支付的费用取决于执行查询时对扫描的源表中被引用的所有列处理的总字节数
MERGE 开始时目标表中所有列的总字节数之和。

对于分区表,处理的字节数按如下方式计算:

DML 语句 处理的字节数
INSERT 执行查询时对扫描的所有分区中被引用的所有列处理的总字节数。
UPDATE 执行查询时对扫描的表的所有分区中被引用的所有列处理的总字节数
UPDATE 开始时所更新表的更新或扫描分区中所有列的总字节数之和。
DELETE 执行查询时对扫描的表的所有分区中被引用的所有列处理的总字节数
DELETE 开始时所修改表的修改或扫描分区中所有列的总字节数之和。
MERGE 如果 MERGE 语句中仅包含 INSERT 子句,您需要支付的费用将取决于执行查询时对扫描的所有分区中被引用的所有列处理的总字节数。
如果 MERGE 语句中包含 UPDATEDELETE 子句,则您需要支付的费用取决于执行查询时对扫描的源表的所有分区中被引用的所有列处理的总字节数
MERGE 开始时目标表的更新、删除或扫描分区中所有列的总字节数之和。

DDL 语句

如果使用按需结算,BigQuery 会根据查询处理的字节数收取数据定义语言 (DDL) 查询的费用。

DDL 语句 处理的字节数
CREATE TABLE 无。
CREATE TABLE ... AS SELECT ... 执行查询时对扫描的表中被引用的所有列处理的总字节数。
CREATE VIEW 无。
DROP TABLE 无。
DROP VIEW 无。

脚本

如果使用按需结算,BigQuery 会根据执行脚本期间处理的字节数收取脚本的费用。

以下价格适用于特定于脚本的语句类型:

  • DECLARE:针对 DEFAULT 表达式中引用的所有表扫描的总字节数。未引用表的 DECLARE 语句不会产生费用。
  • SET:针对该表达式中引用的所有表扫描的总字节数。未引用表的 SET 语句不会产生费用。
  • IF:针对该条件表达式中引用的所有表扫描的总字节数。未引用表的 IF 条件表达式不会产生费用。IF 块中任何未执行的语句都不会产生费用。
  • WHILE:针对该条件表达式中引用的所有表扫描的总字节数。该条件表达式中未引用表的 WHILE 语句不会产生费用。WHILE 块中任何未执行的语句都不会产生费用。
  • CONTINUEITERATE:无相关费用。
  • BREAKLEAVE:无相关费用。
  • BEGINEND:无相关费用。

脚本运行过程中,临时表不会产生存储费用。但是,任何创建、修改或查询表的语句都会产生常规费用。

如果脚本失败,失败前执行的所有语句仍会产生相关费用。失败的语句不会产生任何费用。

脚本价格示例

在以下示例脚本中,每个语句上方都包含注释,说明了其下的语句会产生哪些费用(如果有)。

-- No cost, since no tables are referenced.
DECLARE x DATE DEFAULT CURRENT_DATE();
-- Incurs the cost of scanning string_col from dataset.table.
DECLARE y STRING DEFAULT (SELECT MAX(string_col) FROM dataset.table);
-- Incurs the cost of copying the data from dataset.big_table.  Once the
-- table is created, you are not charged for storage while the rest of the
-- script runs.
CREATE TEMP TABLE t AS SELECT * FROM dataset.big_table;
-- Incurs the cost of scanning column1 from temporary table t.
SELECT column1 FROM t;
-- No cost, since y = 'foo' doesn't reference a table.
IF y = 'foo' THEN
  -- Incurs the cost of scanning all columns from dataset.other_table, if
  -- y was equal to 'foo', or otherwise no cost since it is not executed.
  SELECT * FROM dataset.other_table;
ELSE
  -- Incurs the cost of scanning all columns from dataset.different_table, if
  -- y was not equal to 'foo', or otherwise no cost since it is not executed.
  UPDATE dataset.different_table
  SET col = 10
  WHERE true;
END IF;
-- Incurs the cost of scanning date_col from dataset.table for each
-- iteration of the loop.
WHILE x < (SELECT MIN(date_col) FROM dataset.table) DO
  -- No cost, since the expression does not reference any tables.
  SET x = DATE_ADD(x, INTERVAL 1 DAY);
  -- No cost, since the expression does not reference any tables.
  IF true THEN
    -- LEAVE has no associated cost.
    LEAVE;
  END IF;
  -- Never executed, since the IF branch is always taken, so does not incur
  -- a cost.
  SELECT * FROM dataset.big_table;
END WHILE;

聚簇表

聚簇表可通过剪除数据,使其免于查询处理,从而帮助降低查询费用。此过程称为块剪除。

块剪除

BigQuery 会根据聚簇列中的值对聚簇表中的数据排序,并将这些数据整理为块的形式。

如果您对聚簇表运行查询,并且此查询包含针对聚簇列的过滤条件,则 BigQuery 会使用过滤条件表达式和块元数据来剪除查询要扫描的块。这样一来,BigQuery 就可以仅扫描相关块。

当某个块被剪除后,系统不会对其进行扫描。只有经过扫描的块才会计入查询所处理的数据量(以字节为单位)。对聚簇表运行的查询所处理的字节数,等于系统在所扫描的块内从该查询引用的每个列中读取的字节总数。

如果集群表在使用多个过滤条件的查询中被引用了多次,则 BigQuery 会分别收取各个过滤条件下相应块中列的扫描费用。

聚簇表价格示例

您有一个名为 ClusteredSalesData 的聚簇表。该表按 timestamp 列分区,并按 customer_id 列聚簇。数据整理到下面这些块中:

分区标识符 块 ID 块中 customer_id 的最小值 块中 customer_id 的最大值
20160501 B1 10000 19999
20160501 B2 20000 24999
20160502 B3 15000 17999
20160501 B4 22000 27999

您对该表运行以下查询。此查询包含对 customer_id 列应用的过滤条件。

SELECT
  SUM(totalSale)
FROM
  `mydataset.ClusteredSalesData`
WHERE
  customer_id BETWEEN 20000
  AND 23000
  AND DATE(timestamp) = "2016-05-01"

此查询执行以下操作:

  • 扫描 B2 和 B4 块中的 timestampcustomer_idtotalSale 列。
  • 剪除 B3 块,因为在 timestamp 分区列上应用了 DATE(timestamp) = "2016-05-01" 过滤条件谓语。
  • 剪除 B1 块,因为在 customer_id 聚簇列上应用了 customer_id BETWEEN 20000 AND 23000 过滤条件谓语。

查询 Cloud Storage 中的列式格式

如果外部数据存储在 ORC 或 Parquet 中,则您只需为 BigQuery 读取的列中的字节数付费。由于查询会将来自外部数据源的数据类型转换为 BigQuery 数据类型,因此读取的字节数将根据 BigQuery 数据类型的大小来计算。如需了解数据类型转换,请参阅以下页面: