BigQuery での費用の管理

このページでは、BigQuery で費用を抑えるためのおすすめの方法について説明します。

BigQuery には、クエリを実行するための料金モデルとして次の 2 つがあります。

オンデマンド料金の場合、クエリで処理されるバイト数を削らすことで、コストを抑えることができます。定額料金の場合は、購入するスロット数とスロット コミットメント プランに基づいて固定料金が適用されます。ただし、クエリを最適化すると、スロットの使用量を削減できる場合があります。

SELECT * を避ける

おすすめの方法: 必要な列のみを照会します。

SELECT * の使用は、データを照会するのに最も費用がかかる方法です。SELECT * を使用すると、BigQuery はテーブル内のすべての列をフルスキャンします。

データのテストまたは探索には、SELECT * ではなく、いずれかのデータ プレビュー オプションを使用してください。

LIMIT 句を SELECT * クエリに適用しても、読み取られるデータの量には影響しません。テーブル全体のすべてのバイトの読み取りに対して課金され、クエリは無料枠割り当ての対象としてカウントされます。

代わりに、必要な列のみを照会します。たとえば、SELECT * EXCEPT を使用して、結果から 1 つ以上の列を除外します。

テーブル内のすべての列を対象とするものの、データのサブセットに対してのみクエリを実行する必要がある場合は、以下のことを検討してください。

プレビュー オプションを使用してデータをサンプリングする

おすすめの方法: テーブルデータを探索またはプレビューするためにクエリを実行しないでください。

データを試したり調べたりする場合は、テーブル プレビュー オプションを使用すれば、割り当てに影響を与えることなく、無料でデータを表示できます。

BigQuery は、次のデータ プレビュー オプションをサポートしています。

  • Google Cloud コンソールのテーブルの詳細ページで、[プレビュー] タブをクリックしてデータをサンプリングします。
  • bq コマンドライン ツールで、bq head コマンドを使用して、プレビューする行数を指定します。
  • API で tabledata.list を使用して、指定した行のセットからテーブルデータを取得する。

クエリを実行する前に料金を見積もる

おすすめの方法: クエリを実行する前に、プレビューして費用を見積もります。

クエリは、読み取られたバイト数に基づいて課金されます。クエリを実行する前に費用を見積もるには:

  • Google Cloud コンソールでクエリ検証ツールを表示する
  • Google Cloud 料金計算ツールを使用します。
  • 以下を使用して、ドライランを実行する
    • bq コマンドライン ツールの --dry_run フラグ
    • dryRun パラメータ(API を使用してクエリジョブを送信する場合)

クエリ検証ツールの使用

Google Cloud コンソールでクエリを入力すると、クエリ検証ツールがクエリ構文を検証し、読み取りバイト数を見積もります。この見積もりを使用して、料金計算ツールでクエリ費用を計算できます。

  • クエリが無効な場合は、クエリ検証ツールにエラー メッセージが表示されます。例:

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

  • クエリが有効な場合は、クエリ検証ツールによりクエリ処理に必要なバイト数の見積もりが提供されます。例:

    This query will process 623.1 KiB when run.

ドライランの実行

ドライランを実行するには、次の操作を行います。

Console

  1. Google Cloud Console の [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 タイプで dryRuntrue に設定してクエリジョブを送信します。

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

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))

料金計算ツールの使用

Google Cloud 料金計算ツールでクエリ費用を見積もるには、クエリで処理されるバイト数を MB、GB、TB、PB のいずれかの単位で入力します。BigQuery では月間 1 TB のオンデマンド クエリ処理が無料で提供されるため、クエリで処理されるのが 1 TB 未満の場合、見積もりは $0 になります。

料金計算ツール

課金されるバイト数を制限してクエリ費用を抑える

おすすめの方法: 課金される最大バイト数の設定を使用して、クエリ費用を抑えます。

課金されるクエリのバイト数を制限するには、課金される最大バイト数の設定を使用します。課金される最大バイト数を設定した場合は、クエリが実行される前に、クエリで読み取られるバイト数が推定されます。推定バイト数が上限を超えると、クエリが失敗し、料金は発生しません。

クラスタ化テーブルの場合、クエリに対して課金されるバイト数の推定値は上限値になります。クエリ実行後に請求される実際のバイト数より高くなることがあります。そのため、課金対象の最大バイト数を設定すると、課金される実際のバイト数が課金対象の最大バイト数を超えなくても、クラスタ化テーブルに対するクエリが失敗する場合があります。

課金される最大バイト数を設定したことによってクエリが失敗した場合は、次のようなエラーが返されます。

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

課金される最大バイト数を設定するには:

Console

  1. クエリエディタで、[展開] をクリックし、[クエリの設定] をクリックしてから、[詳細オプション] をクリックします。
  2. [課金される最大バイト数] フィールドに整数を入力します。
  3. [保存] をクリックします。

bq

bq query コマンドを使用し、--maximum_bytes_billed フラグを指定します。

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

API

JobConfigurationQuery または QueryRequestmaximumBytesBilled プロパティを設定します。

クラスタ化テーブルまたはパーティション分割テーブルの使用

ベスト プラクティス: クラスタリングとパーティショニングを使用して、スキャンされるデータの量を減らします。

クラスタリングとパーティショニングにより、クエリで処理されるデータの量を削減できます。クラスタ化テーブルまたはパーティション分割テーブルをクエリする際にスキャンされるパーティション数を制限するには、述部フィルタを使用します。

クラスタ化テーブルにクエリを実行する場合、そのクエリにクラスタ化された列のフィルタが含まれていると、BigQuery はフィルタ式とブロック メタデータを使用して、クエリでスキャンされるブロックをプルーニングします。詳細については、クラスタ化テーブルのクエリをご覧ください。

パーティション分割テーブルをクエリすると、パーティショニング列のフィルタがパーティションのプルーニングに使用され、クエリの費用を抑えることができます。詳細については、パーティション分割テーブルのクエリをご覧ください。

クラスタ化されていないテーブルの費用管理に LIMIT を使用しない

ベスト プラクティス: クラスタ化されていないテーブルでは、費用を管理する手法として LIMIT 句を使用しないでください。

クラスタ化されていないテーブルの場合、クエリに LIMIT 句を適用しても、読み取られるデータの量には影響しません。クエリがサブセットのみを返す場合でも、クエリで示されているテーブル全体のすべてのバイトの読み取りに対して課金されます。クラスタ化テーブルでは、結果を取得するために十分なブロックがスキャンされる場合にスキャンが停止するため、LIMIT 句でスキャンできるバイト数を減らすことができます。スキャンされたバイトに対してのみ課金されます。

ダッシュボードを使用して費用を表示し、監査ログを照会する

おすすめの方法: BigQuery の使用量を調整できるように、課金データを表示するためのダッシュボードを作成します。また、使用パターンを分析できるように、BigQuery への監査ログのストリーミングも検討します。

課金データを BigQuery にエクスポートして、Looker Studio などのツールで可視化できます。課金ダッシュボードの作成方法のチュートリアルについては、BigQuery と Looker Studio を使用した Google Cloud Billing の可視化をご覧ください。

また、監査ログを BigQuery にストリーミングして、ユーザー別のクエリ費用などの使用パターンに関するログを分析することもできます。

データを日付別にパーティション分割する

おすすめの方法: テーブルを日付別に分割します。

可能であれば、BigQuery テーブルを日付別に分割します。テーブルをパーティショニングすることで、関連するデータのサブセットをクエリして、パフォーマンスを向上させ、コストを削減できます。

たとえば、パーティション分割テーブルを照会するときに、_PARTITIONTIME 擬似列を使用して日付または日付の範囲をフィルタ処理します。クエリは、日付または範囲で指定されたパーティション内のデータのみを処理します。

クエリ結果を段階的に実体化する

おすすめの方法: 可能であれば、クエリ結果を段階的に実体化します。

大容量のマルチステージ クエリを作成すると、それを実行するたびに、BigQuery がそのクエリに必要なすべてのデータを読み取ります。クエリが実行されるたびに読み取られるすべてのデータに対して課金されます。

代わりに、クエリを複数のステージに分割し、各ステージでクエリ結果を宛先テーブルに書き込むことにより実体化します。小容量の宛先テーブルを照会することにより、読み取られるデータの量が削減され、費用が削減されます。実体化された結果を保存する費用は、大量のデータを処理する費用よりはるかに少なくなります。

大容量の結果セットの費用を検討する

おすすめの方法: 大容量のクエリ結果を宛先テーブルに書き込む場合は、デフォルトのテーブル有効期限を適用して不要になったデータを削除します。

BigQuery ストレージで大容量の結果セットを維持するには費用がかかります。結果に永続的にアクセスする必要がなければ、デフォルトのテーブル有効期限を使用して自動的にデータを削除するようにします。

詳細については、ストレージの料金をご覧ください。