パーティション分割テーブルの管理

このドキュメントでは、BigQuery でパーティション分割テーブルを管理する方法について説明します。

パーティション メタデータの取得

パーティション分割テーブルに関する情報を取得するには、次の方法があります。

INFORMATION_SCHEMA ビューを使用したパーティション メタデータの取得

INFORMATION_SCHEMA.PARTITIONS ビューにクエリを実行すると、クエリ結果にはパーティションごとに 1 行が含まれます。たとえば、次のクエリでは、mydataset という名前のデータセット内のすべてのテーブル パーティションが一覧表示されます。

SELECT table_name, partition_id, total_rows
FROM `mydataset.INFORMATION_SCHEMA.PARTITIONS`
WHERE partition_id IS NOT NULL

詳細については、INFORMATION_SCHEMA.PARTITIONS をご覧ください。

メタテーブルを使用したパーティション メタデータの取得

レガシー SQL では、__PARTITIONS_SUMMARY__ メタテーブルにクエリを実行して、テーブル パーティションに関するメタデータを取得できます。メタテーブルは、メタデータを含む読み取り専用テーブルです。

次のように __PARTITIONS_SUMMARY__ メタテーブルにクエリを実行します。

#legacySQL
SELECT
  column
FROM
  [dataset.table$__PARTITIONS_SUMMARY__]

__PARTITIONS_SUMMARY__ メタテーブルには次の列があります。

説明
project_id プロジェクトの名前。
dataset_id データセットの名前。
table_id 時間パーティション分割テーブルの名前。
partition_id パーティションの名前(日付)。
creation_time パーティションが作成された日時(UTC 1970 年 1 月 1 日からのミリ秒数)。
last_modified_time パーティションが最後に変更された日時(1970 年 1 月 1 日 UTC からの経過ミリ秒数)。

__PARTITIONS_SUMMARY__ メタテーブルを使用するクエリジョブを実行するには、少なくとも bigquery.jobs.create 権限と bigquery.tables.getData 権限が付与されている必要があります。

BigQuery での IAM ロールの詳細については、アクセス制御をご覧ください。

パーティションの有効期限を設定する

取り込み時間または時間単位の列で分割されたテーブルを作成する場合、パーティションの有効期限を指定できます。この設定では、BigQuery が各パーティションにデータを保持する期間を指定します。この設定は、テーブル内のすべてのパーティションに適用されますが、パーティションごとに個別に計算されます。

パーティションの有効期限はパーティションの境界(UTC)から計算されます。たとえば、日単位パーティショニングでは、パーティションの境界は午前 0 時(00:00:00 UTC)です。テーブルのパーティション有効期限が 6 時間の場合、各パーティションは翌日の 06:00:00 UTC に期限切れになります。パーティションが期限切れになると、BigQuery はそのパーティションのデータを削除します。

データセット レベルでデフォルトのパーティション有効期限を指定することもできます。テーブルにパーティションの有効期限を設定すると、その値によってデフォルトのパーティション有効期限がオーバーライドされます。(テーブルまたはデータセットで)パーティションの有効期限を指定しない場合、パーティションは期限切れになりません。

テーブルの有効期限を設定した場合、その値はパーティションの有効期限よりも優先されます。たとえば、テーブルの有効期限が 5 日間、パーティションの有効期限が 7 日間に設定されている場合、テーブルとテーブル内のすべてのパーティションは 5 日後に削除されます。

テーブルが作成された後はいつでも、テーブルのパーティションの有効期限を更新できます。新しい設定は、パーティションがいつ作成されたかにかかわらず、そのテーブル内のすべてのパーティションに適用されます。既存のパーティションは、新しい有効期限よりも古いとすぐに期限切れになります。同様に、時間単位列でパーティション分割されたテーブルにデータをコピーまたは挿入すると、そのテーブルに対して構成されたパーティション有効期限よりも古いパーティションは直ちに期限切れになります。

パーティションが期限切れになると、BigQuery はそのパーティションを削除します。パーティション データは、タイムトラベル ポリシーとフェイルセーフ ポリシーに従って保持され、課金モデルに応じて課金される場合があります。それまでは、パーティションはテーブル割り当ての計算対象になります。パーティションを直ちに削除するには、パーティションを手動で削除します。

パーティションの有効期限を更新する

パーティション分割テーブルのパーティションの有効期限を更新するには:

コンソールSQLbqAPI

Google Cloud コンソールでパーティションの有効期限を更新することはできません。

ALTER TABLE SET OPTIONS ステートメントを使用します。次の例では、有効期限が 5 日間に更新されます。テーブルのパーティション有効期限を削除するには、partition_expiration_daysNULL に設定します。

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

    [BigQuery] に移動

  2. クエリエディタで次のステートメントを入力します。

    ALTER TABLE mydataset.mytable
      SET OPTIONS (
        -- Sets partition expiration to 5 days
        partition_expiration_days = 5);

  3. [実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリを実行するをご覧ください。

--time_partitioning_expiration フラグを指定して bq update コマンドを発行します。更新するパーティション分割テーブルがデフォルト プロジェクト以外のプロジェクトにある場合は、project_id:dataset の形式でプロジェクト ID をデータセット名に追加します。

bq update \
--time_partitioning_expiration integer_in_seconds \
--time_partitioning_type unit_time \
project_id:dataset.table

ここで

  • integer は、テーブルのパーティションのデフォルトの存続期間(秒)です。最小値はありません。パーティションの日付にこの整数値を足した値が有効期限になります。0 を指定すると、パーティションの有効期限は削除され、パーティションは無期限に有効になります。有効期限のないパーティションは手動で削除する必要があります。
  • unit_time は、テーブルのパーティショニングの粒度に応じて、DAYHOURMONTHYEAR のいずれかになります。この値は、テーブルの作成時に設定した粒度と一致している必要があります。
  • project_id はプロジェクト ID です。
  • dataset は、更新しているテーブルを含むデータセットの名前です。
  • table は更新するテーブルの名前です。

例:

次のコマンドを入力して、mydataset.mytable のパーティションの有効期限を 5 日間(432,000 秒)に更新します。mydataset はデフォルト プロジェクトにあります。

bq update --time_partitioning_expiration 432000 mydataset.mytable

次のコマンドを入力して、mydataset.mytable のパーティションの有効期限を 5 日間(432,000 秒)に更新します。mydataset はデフォルト プロジェクトではなく myotherproject にあります。

bq update \
--time_partitioning_expiration 432000 \
myotherproject:mydataset.mytable

tables.patch メソッドを呼び出し、timePartitioning.expirationMs プロパティを使用してパーティションの有効期限をミリ秒単位で更新します。tables.update メソッドはテーブル リソース全体を置き換えるため、tables.patch メソッドのほうが適切です。

パーティション フィルタ要件を設定する

パーティション分割テーブルを作成するときに、テーブルに対するすべてのクエリに、パーティショニングする列を除外する述語フィルタ(WHERE 句)を含めるように要求できます。BigQuery では、このフィルタを使用して述語と一致しないパーティションをプルーニングできるため、パフォーマンスが向上し、コストを削減できます。

パーティション分割テーブルを作成するときに、パーティション フィルタを要求するオプションを追加する方法については、パーティション分割テーブルの作成をご覧ください。

パーティション分割テーブルにパーティション フィルタを要求する設定がある場合、そのテーブルのすべてのクエリに、パーティショニングする列のみを参照する述語を 1 つ以上含める必要があります。このような述語のないクエリは、次のエラーを返します。

Cannot query over table 'project_id.dataset.table' without a filter that can be used for partition elimination

詳細については、パーティション分割テーブルのクエリをご覧ください。

パーティション フィルタ要件を更新する

パーティション分割テーブルを作成するときに、パーティション フィルタを要求するオプションを有効にしない場合でも、テーブルを更新してオプションを追加できます。

パーティション分割テーブルの作成後に、Google Cloud コンソールでパーティション フィルタを要求することはできません。

ALTER TABLE SET OPTIONS ステートメントを使用して、パーティション フィルタ要件を更新します。次の例では、要件を true に更新します。

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

    [BigQuery] に移動

  2. クエリエディタで次のステートメントを入力します。

    ALTER TABLE mydataset.mypartitionedtable
      SET OPTIONS (
        require_partition_filter = true);

  3. [実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリを実行するをご覧ください。

bq コマンドライン ツールを使用してパーティション フィルタを要求するようにパーティション分割テーブルを更新するには、bq update コマンドを入力して、--require_partition_filter フラグを指定します。

デフォルト プロジェクト以外のプロジェクトにあるパーティション分割テーブルを更新するには、project_id:dataset の形式でプロジェクト ID をデータセットに追加します。

例:

デフォルト プロジェクトで mydatasetmypartitionedtable を更新するには、次のように入力します。

bq update --require_partition_filter mydataset.mytable

myotherprojectmydatasetmypartitionedtable を更新するには、次のように入力します。

bq update --require_partition_filter myotherproject:mydataset.mytable

tables.patch メソッドを呼び出して、requirePartitionFilter プロパティを true に設定すると、パーティション フィルタが要求されます。tables.update メソッドはテーブル リソース全体を置き換えるため、tables.patch メソッドの方が適切です。

このサンプルを試す前に、クライアント ライブラリを使用した 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.Table;

// Sample to update require partition filter on a table.
public class UpdateTableRequirePartitionFilter {

  public static void runUpdateTableRequirePartitionFilter() {
    // TODO(developer): Replace these variables before running the sample.
    String datasetName = "MY_DATASET_NAME";
    String tableName = "MY_TABLE_NAME";
    updateTableRequirePartitionFilter(datasetName, tableName);
  }

  public static void updateTableRequirePartitionFilter(String datasetName, String tableName) {
    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();

      Table table = bigquery.getTable(datasetName, tableName);
      table.toBuilder().setRequirePartitionFilter(true).build().update();

      System.out.println("Table require partition filter updated successfully");
    } catch (BigQueryException e) {
      System.out.println("Table require partition filter was not updated \n" + e.toString());
    }
  }
}

パーティション分割テーブルをコピーする

単一のパーティション分割テーブルをコピーするプロセスは、単一の標準テーブルをコピーするプロセスと同じです。詳細については、テーブルのコピーをご覧ください。

パーティション分割テーブルをコピーする際は、以下の点に注意してください。

  • パーティション分割テーブルを新しい宛先テーブルにコピーする場合
    すべてのパーティショニング情報がテーブルとともにコピーされます。新しいテーブルのパーティションは古いテーブルと同じです。
  • パーティション分割されていないテーブルを既存のパーティション分割テーブルにコピーする場合
    このオペレーションは、取り込み時間パーティショニングでのみサポートされています。BigQuery は、現在の日付を表すパーティションにソースデータをコピーします。このオペレーションは、時間単位の列パーティション分割テーブルまたは整数範囲パーティション分割テーブルではサポートされていません。
  • パーティション分割テーブルを別のパーティション分割テーブルにコピーする場合
    コピー元テーブルと宛先テーブルのパーティションの設定が一致している必要があります。
  • パーティション分割テーブルを分割されていないテーブルにコピーする場合
    宛先テーブルは分割されていない状態です。
  • 複数のパーティション分割テーブルのコピー

    同じジョブで複数のテーブルをパーティション分割テーブルにコピーする場合、コピー元にパーティション分割テーブルとパーティション分割されていないテーブルが混在していてはなりません。

    コピー元のテーブルがすべてパーティション分割テーブルの場合、すべてのコピー元テーブルのパーティションの設定がコピー先テーブルのパーティションの設定と一致している必要があります。

既存のテーブルにコピーするときに、コピー先テーブルにデータを追加するか上書きするかを指定できます。

個々のパーティションをコピーする

1 つ以上のパーティションから別のテーブルにデータをコピーできます。

コンソールbqAPI

Google Cloud コンソールでは、パーティションのコピーはサポート対象外です。

パーティションをコピーするには、bq コマンドライン ツールの bq cp(コピー)コマンドに $20160201 などのパーティション デコレータ($date)を指定して使用します。

オプションのフラグを使用して、コピー先パーティションの書き込み処理を制御できます。

  • -a または --append_table を指定すると、コピー元パーティションのデータがコピー先データセット内の既存のテーブルまたはパーティションに追加されます。
  • -f または --force を指定すると、コピー先データセット内の既存のテーブルまたはパーティションが上書きされますが、確認を求めるプロンプトは表示されません。
  • -n または --no_clobber を指定すると、コピー先データセット内にテーブルまたはパーティションが存在する場合、「Table '<var>project_id:dataset.table</var> or <var>table$date</var>' already exists, skipping.」というエラー メッセージが返されます。-n が指定されていない場合は、デフォルトの動作として、コピー先のテーブルやパーティションを置き換えるかどうかの選択を求めるプロンプトが表示されます。
  • --destination_kms_key は顧客管理の Cloud KMS 鍵で、コピー先テーブルまたはパーティションを暗号化するために使用します。

cp コマンドは --time_partitioning_field フラグや --time_partitioning_type フラグをサポートしません。コピージョブを使用して取り込み時間パーティション分割テーブルをパーティション分割テーブルに変換することはできません。

--destination_kms_key はここでは説明しません。詳細については、Cloud KMS 鍵によるデータの保護をご覧ください。

コピー元またはコピー先のデータセットがデフォルト以外のプロジェクトにある場合は、project_id:dataset の形式でプロジェクト ID をデータセット名に追加します。

(省略可)--location フラグを指定して、その値をロケーションに設定します。

bq --location=location cp \
-a -f -n \
project_id:dataset.source_table$source_partition \
project_id:dataset.destination_table$destination_partition

ここで

  • location はロケーションの名前です。--location フラグは省略可能です。たとえば、BigQuery を東京リージョンで使用している場合は、このフラグの値を asia-northeast1 に設定します。.bigqueryrc ファイルを使用してロケーションのデフォルト値を設定できます。
  • project_id はプロジェクト ID です。
  • dataset は、コピー元またはコピー先データセットの名前です。
  • source_table は、コピーするテーブルです。
  • source_partition は、コピー元パーティションのパーティション デコレータです。
  • destination_table は、コピー先データセット内のテーブルの名前です。
  • destination_partition は、コピー先パーティションのパーティション デコレータです。

例:

パーティションを新しいテーブルにコピーする

次のコマンドを入力して mydataset.mytable にある 2018 年 1 月 30 日のパーティションを別のテーブル(mydataset.mytable2)にコピーします。mydataset はデフォルト プロジェクトにあります。

bq cp -a 'mydataset.mytable$20180130' mydataset.mytable2

パーティションをパーティション分割されていないテーブルにコピーする

次のコマンドを入力して mydataset.mytable にある 2018 年 1 月 30 日のパーティションをパーティション分割されていないテーブル(mydataset2.mytable2)にコピーします。-a ショートカットが指定されているため、パーティションのデータはパーティション分割されていないコピー先テーブルに追加されます。データセットは両方ともデフォルト プロジェクトにあります。

bq cp -a 'mydataset.mytable$20180130' mydataset2.mytable2

次のコマンドを入力して mydataset.mytable にある 2018 年 1 月 30 日のパーティションをパーティション分割されていないテーブル(mydataset2.mytable2)にコピーします。-f ショートカットが指定されているため、パーティション分割されていないコピー先テーブルがプロンプトなしで上書きされます。

bq --location=US cp -f 'mydataset.mytable$20180130' mydataset2.mytable2

パーティションを別のパーティション分割テーブルにコピーする

次のコマンドを入力して mydataset.mytable にある 2018 年 1 月 30 日のパーティションを別のパーティション分割テーブル(mydataset2.mytable2)にコピーします。-a ショートカットが指定されているため、パーティションのデータはコピー先テーブルに追加されます。コピー先テーブルにはパーティション デコレータが指定されていないため、コピー元のパーティション キーが維持され、データはコピー先テーブルの 2018 年 1 月 30 日のパーティションにコピーされます。コピー先テーブルでパーティション デコレータを指定して特定のパーティションにデータをコピーすることもできます。mydataset はデフォルト プロジェクトにあります。mydataset2 はデフォルト プロジェクトではなく myotherproject にあります。

bq --location=US cp \
-a \
'mydataset.mytable$20180130' \
myotherproject:mydataset2.mytable2

次のコマンドを入力して mydataset.mytable にある 2018 年 1 月 30 日のパーティションを別のパーティション分割テーブルの 2018 年 2 月 20 日のパーティション(mydataset2.mytable2)にコピーします。-f ショートカットが指定されているため、コピー先テーブルの 2018 年 2 月 20 日のパーティションがプロンプトなしに上書きされます。パーティション デコレータを使用しない場合、コピー先テーブルのすべてのデータが上書きされます。mydataset はデフォルト プロジェクトにあります。mydataset2 はデフォルト プロジェクトではなく myotherproject にあります。

bq cp \
-f \
'mydataset.mytable$20180130' \
'myotherproject:mydataset2.mytable2$20180220'

次のコマンドを入力して mydataset.mytable にある 2018 年 1 月 30 日のパーティションを別のパーティション分割テーブル(mydataset2.mytable2)にコピーします。mydataset はデフォルト プロジェクトにあります。mydataset2 はデフォルト プロジェクトではなく myotherproject にあります。コピー先テーブルにデータがある場合は、デフォルトの動作として、上書きするかどうかを確認するプロンプトが表示されます。

bq cp \
'mydataset.mytable$20180130' \
myotherproject:mydataset2.mytable2

複数のパーティションをコピーする場合は、カンマ区切りのリストとして指定します。

bq cp \
'mydataset.mytable$20180130,mydataset.mytable$20180131' \
myotherproject:mydataset.mytable2

jobs.insert メソッドを呼び出して、copy ジョブを構成します。(省略可)ジョブリソースjobReference セクションにある location プロパティでリージョンを指定します。

ジョブ構成で以下のプロパティを指定します。

  • sourceTables プロパティに、コピー元のデータセット、テーブル、パーティションを入力します。
  • destinationTable プロパティに、コピー先のデータセットとテーブルを入力します。
  • writeDisposition プロパティを使用して、コピー先のテーブルまたはパーティションにデータを追加するか上書きするかを指定します。

複数のパーティションをコピーするには、sourceTables プロパティにコピー元パーティション(データセット名とテーブル名を含む)を入力します。

パーティションを削除する

パーティション分割テーブルから個々のパーティションを削除できます。ただし、特別な __NULL__ または __UNPARTITIONED__ パーティションは削除できません。

現時点では、一度に削除できるパーティションは 1 つだけです。

パーティションが 2 つある特別なパーティションではない限り、パーティションのデコレータを指定することでパーティションを削除できます。

パーティション分割テーブルのパーティションを削除するには:

コンソールSQLbqAPI

Google Cloud コンソールでは、パーティションの削除はサポート対象外です。

修飾子付きの DELETE ステートメントがパーティション内のすべての行をカバーする場合、BigQuery はパーティション全体を削除します。この削除は、バイトをスキャンすることもスロットを消費することもなく行われます。次の DELETE ステートメントの例では、_PARTITIONDATE 疑似列のフィルタのパーティション全体を対象としています。

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

    [BigQuery] に移動

  2. クエリエディタで次のステートメントを入力します。

    DELETE mydataset.mytable
    WHERE _PARTITIONDATE IN ('2076-10-07', '2076-03-06');

  3. [実行] をクリックします。

クエリの実行方法については、インタラクティブ クエリを実行するをご覧ください。

--table フラグ(または -t ショートカット)を指定して bq rm コマンドを使用し、パーティション デコレータを指定して、特定のパーティションを削除します。

bq rm --table project_id:dataset.table$partition

ここで

  • project_id はプロジェクト ID です。省略した場合は、デフォルトのプロジェクトが使用されます。
  • dataset は、テーブルを含むデータセットの名前です。
  • table はテーブルの名前です。
  • partition は、削除するパーティションのパーティション デコレータです。

パーティション デコレータには、パーティショニングのタイプに応じて次の形式があります。

  • 時間単位パーティション: yyyymmddhh。例: $2016030100
  • 日単位パーティション: yyyymmdd。例: $20160301
  • 月単位パーティション: yyyymm。例: $201603
  • 年単位パーティション: yyyy。例: $2016
  • 整数範囲パーティション: パーティション範囲の始点。例: $20

アクションの確認を求めるプロンプトが bq コマンドライン ツールに表示されます。確認をスキップするには、--force フラグ(または -f ショートカット)を使用します。

例:

デフォルト プロジェクトの mydataset.mytable という名前の日単位パーティション分割テーブルから、2016 年 3 月 1 日のパーティションを削除します。

bq rm --table 'mydataset.mytable$20160301'

月単位パーティション分割テーブルから、2016 年 3 月のパーティションを削除します。

bq rm --table 'mydataset.mytable$201603'

mydataset.mytable という名前の整数範囲パーティション分割テーブルから、20 で始まる整数範囲を削除します。

bq rm --table 'mydataset.mytable$20'

tables.delete メソッドを呼び出して、tableId パラメータを使用してテーブルおよびパーティション デコレータを指定します。

パーティション分割テーブルのセキュリティ

パーティション分割テーブルのアクセス制御は、標準テーブルのアクセス制御と同じです。さらに詳しい内容については、テーブル アクセス制御の概要をご覧ください。