パーティション分割テーブルの概要

このページでは、BigQuery でのパーティション分割テーブルの概要について説明します。

パーティション分割テーブルはパーティションと呼ばれるセグメントに分割された特殊なテーブルで、データの管理や照会をより簡単に行うことができます。大きいテーブルを小さいパーティションに分割することでクエリのパフォーマンスを向上させることができ、クエリで読み取られるバイト数を減らすことによってコストを管理できます。

BigQuery テーブルを分割する方法は次のとおりです。

  • 時間単位の列: テーブルの TIMESTAMPDATE、または DATETIME 列に基づいてテーブルが分割されます。

  • 取り込み時間: BigQuery がデータを取り込む際のタイムスタンプに基づいてテーブルが分割されます。

  • 整数範囲: テーブルは整数列に基づいて分割されます。

パーティショニングする列の値でクエリがフィルタされる場合、BigQuery はフィルタに一致するパーティションをスキャンし、残りのパーティションをスキップできます。このプロセスは「プルーニング」と呼ばれます。

時間単位列パーティショニング

テーブルのパーティションは、テーブルの DATETIMESTAMP または DATETIME 列で分割できます。テーブルにデータを書き込むと、BigQuery は列の値に基づいて、自動的に正しいパーティションにデータを入力します。

TIMESTAMP 列と DATETIME 列では、パーティションを時間単位、日単位、月単位、年単位のいずれで作成できます。DATE 列の場合、パーティションは日単位、月単位、年単位で作成できます。パーティションの境界は UTC 時間に基づきます。

たとえば、月別パーティショニングで DATETIME 列にテーブルを分割するとします。テーブルに次の値を挿入すると、行は次のパーティションに書き込まれます。

列の値 パーティション(月単位)
DATETIME("2019-01-01") 201901
DATETIME("2019-01-15") 201901
DATETIME("2019-04-30") 201904

さらに、次の 2 つの特殊パーティションが作成されます。

  • __NULL__: パーティショニングする列で NULL 値を持つ行が含まれます。
  • __UNPARTITIONED__: パーティショニングする列の値が 1960-01-01 より前、または 2159-12-31 より後の行を含みます。

取り込み時間パーティショニング

取り込み時間で分割されたテーブルを作成すると、BigQuery はデータを取り込む時間に基づいて、パーティションに自動的に行を割り当てます。パーティションは、時間単位、日単位、月単位、年単位から選択できます。パーティションの境界は UTC 時間に基づきます。

取り込み時間パーティション分割テーブルには、_PARTITIONTIME という名前の疑似列があります。この列の値は、パーティションの境界(時間単位や日単位など)で切り捨てられた各行の取り込み時間です。たとえば、時間単位のパーティショニングで取り込み時間パーティション分割テーブルを作成し、次の時点でデータを送信するとします。

取り込み時間 _PARTITIONTIME パーティション(時間単位)
2021-05-07 17:22:00 2021-05-07 17:00:00 2021050717
2021-05-07 17:40:00 2021-05-07 17:00:00 2021050717
2021-05-07 18:31:00 2021-05-07 18:00:00 2021050718

この例のテーブルは時間単位のパーティショニングを使用しているため、_PARTITIONTIME の値は 1 時間の境界で切り捨てられます。BigQuery はこの値を使用して、データの正しいパーティションを決定します。

特定のパーティションにデータを書き込むこともできます。たとえば、過去のデータの読み込みやタイムゾーンの調整ができます。0001-01-01 から 9999-12-31 までの有効な日付を使用できます。ただし、DML ステートメントは、1970-01-01 より前、および 2159-12-31 より後の日付を参照できません。詳細については、特定のパーティションにデータを書き込むをご覧ください。

_PARTITIONTIME の代わりに _PARTITIONDATE を使用することもできます。_PARTITIONDATE 擬似列には、_PARTITIONTIME 擬似列の値に対応する UTC の日付が格納されます。

整数範囲パーティショニング

特定の INTEGER 列の値の範囲に基づいてテーブルを分割できます。整数範囲パーティション分割テーブルを作成する方法は次のとおりです。

  • パーティショニング列。
  • 範囲パーティショニングの開始値(この値を含む)。
  • 範囲パーティショニングの終了値(この値を含まない)。
  • パーティション内の各範囲の間隔。

たとえば、次の仕様で整数範囲パーティションを作成するとします。

引数
列名 customer_id
開始 0
終了 100
間隔 10

テーブルは、customer_id 列において、10 の間隔の範囲にパーティション分割されます。0 から 9 の値は 1 つのパーティションに入り、10 から 19 は次のパーティションに入ります。この処理が 99 まで続きます。この範囲外の値は、__UNPARTITIONED__ という名前のパーティションに入ります。customer_idNULL である行は、__NULL__ という名前のパーティションに入ります。

日別、時間別、月別、年別のいずれかのパーティショニングを選択します。

時間単位列または取り込み時間でテーブルをパーティション分割する場合、日別、時間別、月別、年別のいずれかのパーティションを選択します。

  • 日別のパーティショニングはデフォルトのパーティショニング タイプです。データが長期間にわたって分散している場合や、データが継続的に追加される場合は、日別パーティショニングが適しています。

  • 大量のデータが短期間(通常は 6 か月未満のタイムスタンプ値)のデータ範囲にある場合は、時間別パーティショニングを選択します。時間別のパーティショニングを選択する場合、パーティションの数がパーティションの制限を超えないようにしてください。

  • テーブルの 1 日あたりのデータ量は比較的少ないものの、長い期間にわたる場合は、月別または年別パーティショニングを選択します。このオプションは、ワークフローで長い期間(例: 500 日超)にわたる行の更新または追加を頻繁に行う必要がある場合にも推奨されます。これらのシナリオでは、パーティショニング列で月別または年別のパーティショニングをクラスタリングと併用すると、最適なパフォーマンスを実現します。詳細については、このページのパーティショニングとクラスタリングをご覧ください。

パーティショニングとクラスタリング

パーティショニングとクラスタリングのどちらでも、パフォーマンスが向上し、クエリ費用を抑えられます。

次の状況では、クラスタリングを使用します。

  • クエリを実行する前に、厳密な費用保証を行う必要がない場合。
  • パーティショニングだけで許容されるよりも細かい粒度が必要です。同じ列をパーティショニングとクラスタリングの両方に使用すると、パーティショニングのメリット以外にクラスタリングのメリットを得ることができます。
  • 通常、クエリによって特定の複数列に対するフィルタまたは集計が使用されている場合。
  • 1 つの列または列グループの値のカーディナリティが大きい。

次の状況では、パーティショニングを使用します。

  • クエリを実行する前にクエリ費用を把握したい。パーティション プルーニングをクエリ実行の前に行い、ドライランでのパーティショニング プルーニングの後にクエリ費用を入手できます。クエリ実行中にクラスタ プルーニングを行うと、費用はクエリ終了後にのみ入手できます。

  • パーティション レベルの管理が必要な場合。たとえば、パーティションの有効期限を設定する場合、特定のパーティションにデータを読み込む場合、パーティションを削除する場合などです。

  • データのパーティショニング方法と各パーティション内でパーティショニングするデータを指定したい場合。たとえば、時間の粒度を定義したい場合や、整数範囲のパーティショニングのために、テーブルの分割に使用する範囲を定義したい場合です。

次のような状況では、パーティショニングではなくクラスタリングをおすすめします。

  • パーティショニングにより、パーティションごとに少量のデータ(約 1 GB 未満)が生成される場合。
  • パーティショニングにより、パーティション分割テーブルの上限を超える多数のパーティションが生成される場合。
  • パーティショニングにより、テーブル内の大部分のパーティションが頻繁に(たとえば、数分ごとに)変更されるミューテーション オペレーションが生成される場合。

パーティショニングとクラスタリングを組み合わせることもできます。データはまずパーティション分割されてから、クラスタリング列ごとに各パーティションのデータがクラスタ化されます。

テーブルにクエリが実行されると、パーティショニングでは、パーティション プルーニングに基づきクエリ費用の上限が設定されます。クラスタ プルーニングが原因でクエリが実際に実行されると、他のクエリ費用を削減できる可能性があります。

パーティショニングとシャーディング

テーブル シャーディングは、[PREFIX]_YYYYMMDD などの名前の接頭辞を使用して複数のテーブルにデータを格納する方法です。

パーティション分割テーブルのほうがパフォーマンスが向上するため、テーブルのシャーディングよりもパーティショニングをおすすめします。シャーディングされたテーブルでは、BigQuery は各テーブルのスキーマとメタデータのコピーを保持する必要があります。BigQuery では、クエリされた各テーブルの権限の検証も必要になる場合があります。この方法はさらに、クエリのオーバーヘッドを増やし、クエリのパフォーマンスを低下させます。

以前に日付別テーブルを作成している場合は、取り込み時間パーティション分割テーブルに変換できます。詳細については、日付別テーブルの取り込み時間パーティション分割テーブルへの変換をご覧ください。

制限事項

レガシー SQL を使用して、パーティション分割テーブルをクエリすることや、クエリ結果をパーティション分割テーブルに書き込むことはできません。

時間単位の列パーティション分割テーブルには次の制限があります。

  • パーティショニング列は、スカラー DATE 列、TIMESTAMP 列、DATETIME 列のいずれかであることが必要です。列のモードは REQUIRED または NULLABLE にできますが、REPEATED(配列ベース)にすることはできません。
  • パーティショニング列はトップレベル フィールドであることが必要です。分割する列として RECORDSTRUCT)のリーフ フィールドは使用できません。

整数範囲パーティション分割テーブルには次の制限があります。

  • 分割する列は INTEGER 列である必要があります。列のモードは REQUIRED または NULLABLE にできますが、REPEATED(配列ベース)にすることはできません。
  • 分割する列はトップレベル フィールドである必要があります。分割する列として RECORDSTRUCT)のリーフ フィールドは使用できません。

パーティション分割テーブルの割り当てと制限

パーティション分割テーブルには BigQuery で上限が定義されています。

割り当てと上限は、パーティション分割テーブルに対して実行できる次のようなさまざまな種類のジョブにも適用されます。

すべての割り当てと制限の詳細については、割り当てと制限をご覧ください。

パーティション分割テーブルの料金

BigQuery で分割テーブルを作成して使用する場合、パーティションに格納されるデータの量とデータに対して実行するクエリに基づいて料金が発生します。

パーティションへのデータの読み込み、パーティションのコピー、パーティションからのデータのエクスポートなど、分割テーブルのオペレーションの多くは無料です。これらのオペレーションは無料ですが、BigQuery の割り当てと制限が適用されます。すべての無料オペレーションについては、料金ページの無料のオペレーションをご覧ください。

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

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

次のステップ