キャッシュに保存されているクエリ結果を使用する

BigQuery はすべてのクエリ結果をテーブルに書き込みます。テーブルはユーザーが明示的に指定したテーブルか(宛先テーブル)、一時的なキャッシュ結果テーブルのいずれかです。一時的なキャッシュ結果テーブルは、ユーザー別、プロジェクト別に保持されます。キャッシュに保存されるクエリ結果テーブルにはストレージの費用がかかりませんが、クエリ結果を永続テーブルに書き込む場合はそのデータの保存に対して料金が発生します。

インタラクティブ クエリとバッチクエリの両方を含むすべてのクエリの結果は、一部の例外を除いて、一時テーブルに約 24 時間キャッシュされます。

制限事項

クエリ キャッシュの使用には以下の制限があります。

  • 同じクエリを重複して実行すると、BigQuery はキャッシュに保存された結果を再利用しようとします。キャッシュからデータを取得するには、重複するクエリテキストを元のクエリと同じにする必要があります。
  • クエリ結果がキャッシュ結果テーブルに存続するためには、結果セットを最大レスポンス サイズよりも小さくする必要があります。サイズの大きな結果セットの管理について詳しくは、大きいクエリ結果を返すをご覧ください。
  • キャッシュ結果テーブルは DML ステートメントのターゲットにできません。
  • 現在のセマンティックでは可能ですが、キャッシュに保存された結果を依存ジョブの入力として使用することは推奨されません。たとえば、キャッシュ テーブルから結果を取得するクエリジョブを送信しないでください。その代わりに、結果を名前付き宛先テーブルに書き込んでください。簡単にクリーンアップできるよう、データセット レベルの defaultTableExpirationMs プロパティなどの機能でデータを一定期間後に自動的に期限切れにできます。

料金と割り当て

キャッシュに保存されたクエリ結果は一時テーブルとして保存されます。キャッシュに保存されたクエリ結果が一時テーブルに保存される場合、料金はかかりません。クエリ結果がキャッシュ結果テーブルから取得された場合、ジョブ統計プロパティ statistics.query.cacheHittrue として返され、そのクエリについては課金されません。キャッシュに保存された結果を使用したクエリは、課金の対象となりませんが、BigQuery の割り当てポリシーの対象にはなります。キャッシュに保存された結果を使用したクエリには、コスト削減に加えて、非常に高速であるという利点もあります。これは BigQuery が結果セットを計算する必要がないためです。

クエリのキャッシュの例外

次の場合、クエリ結果はキャッシュに保存されません。

  • 宛先テーブルをジョブ構成、Google Cloud コンソール、bq コマンドライン ツール、または API で指定する場合
  • 結果をキャッシュに保存した後で、参照するテーブルまたは論理ビューが変更された場合
  • クエリによって参照されているいずれかのテーブルが最近ストリーミング挿入を受信していたとき(テーブルには書き込み最適化ストレージのデータが含まれている)。新しい行を受け取ったかどうかは問いません。
  • CURRENT_TIMESTAMP()CURRENT_DATE といった日時関数や SESSION_USER() 関数など、実行タイミングによって異なる値を返す非決定性関数がクエリで使用されている場合
  • ワイルドカードを使用して複数のテーブルに対してクエリを実行する場合
  • キャッシュに保存された結果が期限切れとなった場合。通常、キャッシュの存続期間は 24 時間ですが、キャッシュへの保存はベストエフォート式であり、それより前に無効になることがあります
  • Cloud Storage 以外の外部データソースに対してクエリを実行する場合(Cloud Storage での GoogleSQL クエリでは、クエリ結果のキャッシュへの保存がサポートされています)。
  • 列レベルのセキュリティで保護されているテーブルに対してクエリが実行される場合、結果はキャッシュに保存されないことがあります。
  • 行レベルのセキュリティで保護されているテーブルに対してクエリが実行される場合、結果はキャッシュに保存されません。

キャッシュされた結果の保存方法

クエリを実行すると、一時的なキャッシュ結果テーブルは、匿名データセットと呼ばれる特別な種類の非表示データセットに作成されます。匿名データセットに対するアクセス権は、IAM リソース階層モデル(プロジェクトと組織の権限)から権限を継承する通常のデータセットとは異なり、データセット所有者に限られます。匿名データセットの所有者は、キャッシュされた結果を生成したクエリを実行したユーザーです。また、ユーザーがプロジェクトにアクセスできることを確認するため、プロジェクトに対する bigquery.jobs.create 権限が確認されます。

BigQuery は、匿名データセットの共有をサポートしていません。クエリ結果を共有する場合は、匿名データセットに保存されている、キャッシュされた結果を使用しないでください。その代わりに、結果を名前付き宛先テーブルに書き込んでください。

クエリを実行するユーザーは、データセットとキャッシュ結果テーブルへの完全アクセス権を持っていますが、従属ジョブの入力としてそれらを使用することはおすすめしません。

匿名データセットの名前の先頭はアンダースコアです。これにより、Google Cloud コンソールのデータセットのリストで匿名データセットが非表示になります。bq コマンドライン ツールまたは API を使用して、匿名データセットを一覧表示し、匿名データセットのアクセス制御を監査できます。

キャッシュに保存されている結果の取得を無効にする

[Use cached results] オプションでは、クエリ対象のテーブルが変更された場合を除いて、以前に実行された同じクエリの結果が再利用されます。キャッシュされた結果の使用が役立つのは、クエリを繰り返し実行する場合のみです。新規のクエリでは [Use cached results] オプションの効果がありませんが、デフォルトで有効になっています。

[Use cached results] オプションを無効にしてクエリを繰り返し実行すると、既存のキャッシュされた結果が上書きされます。この場合、BigQuery でクエリ結果を計算する必要があり、そのクエリに対して課金が発生します。これは、ベンチマークに非常に役立ちます。

キャッシュされた結果の取得を無効にしてクエリジョブの実行評価を強制的に行う場合は、クエリジョブの configuration.query.useQueryCache プロパティを false に設定します。

[キャッシュされた結果を使用] オプションを無効にするには:

コンソール

  1. Google Cloud コンソールを開きます。
    [BigQuery] ページに移動

  2. [クエリを新規作成] をクリックします。

  3. [クエリエディタ] テキスト領域に有効な SQL クエリを入力します。

  4. [展開] をクリックして、[クエリの設定] を選択します。

    クエリの設定

  5. [キャッシュの設定] で、[キャッシュに保存された結果を使用] をオフにします。

bq

クエリ キャッシュを上書きするには、nouse_cache フラグを指定します。次の例では、BigQuery が既存のキャッシュされた結果を使用することなく、クエリを強制的に処理します。

 bq query \
 --nouse_cache \
 --batch \
 'SELECT
    name,
    count
  FROM
    `my-project`.mydataset.names_2013
  WHERE
    gender = "M"
  ORDER BY
    count DESC
  LIMIT
    6'

API

キャッシュに保存されている結果を使用せずにクエリを処理するには、query ジョブ構成で useQueryCache プロパティを false に設定します。

Go

このサンプルを試す前に、クライアント ライブラリを使用した BigQuery クイックスタートGo の手順に沿って設定を行ってください。詳細については、BigQuery Go API のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。

import (
	"context"
	"fmt"
	"io"

	"cloud.google.com/go/bigquery"
	"google.golang.org/api/iterator"
)

// queryDisableCache demonstrates issuing a query and requesting that the query cache is bypassed.
func queryDisableCache(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 corpus FROM `bigquery-public-data.samples.shakespeare` GROUP BY corpus;")
	q.DisableQueryCache = true
	// Location must match that of the dataset(s) referenced in the query.
	q.Location = "US"

	// Run the query and print results when the query job is completed.
	job, err := q.Run(ctx)
	if err != nil {
		return err
	}
	status, err := job.Wait(ctx)
	if err != nil {
		return err
	}
	if err := status.Err(); err != nil {
		return err
	}
	it, err := job.Read(ctx)
	for {
		var row []bigquery.Value
		err := it.Next(&row)
		if err == iterator.Done {
			break
		}
		if err != nil {
			return err
		}
		fmt.Fprintln(w, row)
	}
	return nil
}

Java

キャッシュに保存されている結果を使用せずにクエリを処理するには、QueryJobConfiguration の作成時に setUseQueryCachefalse に設定します。

import com.google.cloud.bigquery.BigQuery;
import com.google.cloud.bigquery.BigQueryException;
import com.google.cloud.bigquery.BigQueryOptions;
import com.google.cloud.bigquery.QueryJobConfiguration;
import com.google.cloud.bigquery.TableResult;

// Sample to running a query with the cache disabled.
public class QueryDisableCache {

  public static void runQueryDisableCache() {
    String query = "SELECT corpus FROM `bigquery-public-data.samples.shakespeare` GROUP BY corpus;";
    queryDisableCache(query);
  }

  public static void queryDisableCache(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)
              // Disable the query cache to force live query evaluation.
              .setUseQueryCache(false)
              .build();

      TableResult results = bigquery.query(queryConfig);

      results
          .iterateAll()
          .forEach(row -> row.forEach(val -> System.out.printf("%s,", val.toString())));

      System.out.println("Query disable cache performed successfully.");
    } catch (BigQueryException | InterruptedException 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');

async function queryDisableCache() {
  // Queries the Shakespeare dataset with the cache disabled.

  // Create a client
  const bigquery = new BigQuery();

  const query = `SELECT corpus
    FROM \`bigquery-public-data.samples.shakespeare\`
    GROUP BY corpus`;
  const options = {
    query: query,
    // Location must match that of the dataset(s) referenced in the query.
    location: 'US',
    useQueryCache: false,
  };

  // Run the query as a job
  const [job] = await bigquery.createQueryJob(options);
  console.log(`Job ${job.id} started.`);

  // Wait for the query to finish
  const [rows] = await job.getQueryResults();

  // Print the results
  console.log('Rows:');
  rows.forEach(row => console.log(row));
}

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

// Extract query results
$queryResults = $bigQuery->runQuery($jobConfig);

$i = 0;
foreach ($queryResults as $row) {
    printf('--- Row %s ---' . PHP_EOL, ++$i);
    foreach ($row as $column => $value) {
        printf('%s: %s' . PHP_EOL, $column, json_encode($value));
    }
}
printf('Found %s row(s)' . PHP_EOL, $i);

Python

このサンプルを試す前に、クライアント ライブラリを使用した BigQuery クイックスタートPython の手順に沿って設定を行ってください。詳細については、BigQuery Python API のリファレンス ドキュメントをご覧ください。

BigQuery に対する認証を行うには、アプリケーションのデフォルト認証情報を設定します。詳細については、ローカル開発環境の認証を設定するをご覧ください。

from google.cloud import bigquery

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

job_config = bigquery.QueryJobConfig(use_query_cache=False)
sql = """
    SELECT corpus
    FROM `bigquery-public-data.samples.shakespeare`
    GROUP BY corpus;
"""
query_job = client.query(sql, job_config=job_config)  # Make an API request.

for row in query_job:
    print(row)

キャッシュを確実に使用する

jobs.insert メソッドを使用してクエリを実行する場合、query ジョブ構成の createDisposition プロパティを CREATE_NEVER に設定することにより、キャッシュされた結果を使用できない場合にクエリジョブを強制的に失敗させることができます。

クエリ結果がキャッシュに存在しない場合は、NOT_FOUND エラーが返されます。

bq

クエリ キャッシュからの結果を要求するには、--require_cache フラグを使用します。次の例では、結果がキャッシュに存在する場合に、BigQuery でクエリを処理しています。

 bq query \
 --require_cache \
 --batch \
 'SELECT
    name,
    count
  FROM
    `my-project`.mydataset.names_2013
  WHERE
    gender = "M"
  ORDER BY
    count DESC
  LIMIT
    6'

API

キャッシュに保存されている既存の結果を使用してクエリを処理するには、query ジョブ構成で createDisposition プロパティCREATE_NEVER に設定します。

キャッシュの使用を検証する

BigQuery がキャッシュを使用して結果を返したかどうかを判定する方法は 2 つあります。

  • Google Cloud コンソールを使用する。[クエリ結果] に移動し、[ジョブ情報] をクリックします。[処理されたバイト数] には 0 B(キャッシュされた結果)と表示されます。
  • BigQuery API を使用する。クエリ結果の cacheHit プロパティが true に設定されます。

列レベルのセキュリティの影響

デフォルトでは、BigQuery はクエリ結果を 24 時間キャッシュに保存しますが、前述の例外があります。列レベルのセキュリティで保護されているテーブルに対するクエリはキャッシュに保存されない場合があります。BigQuery が結果をキャッシュに保存する場合は、24 時間のキャッシュ保存期間が適用されます。

ポリシータグに使用されている「Data Catalog のきめ細かい読み取り」のロールからグループまたはユーザーを削除しても、24 時間のキャッシュ保存は無効になりません。「Data Catalog のきめ細かい読み取り」アクセス コントロール グループへの変更はすぐに反映されますが、変更によってキャッシュが無効になることはありません。

ユーザーがクエリを実行しても、クエリ結果は画面に表示されたままになります。また、過去 24 時間以内にデータにアクセスできなくなった場合でも、キャッシュから結果を取得できます。

ユーザーがポリシータグの「Data Catalog のきめ細かい読み取り」のロールから削除されてから 24 時間は、以前に表示が許可されたデータのキャッシュ データにアクセスできます。行がテーブルに追加されると、結果がキャッシュに保存されても、追加された行は表示されません。