【正解】D
【0からの解説】
①前提知識
・パーティション分割:テーブルを日付・時刻列などでセグメント(パーティション)に分け、WHERE 句で絞り込んだパーティションだけを読み取る仕組みです(パーティション プルーニング)。オンデマンド料金はスキャンしたバイト数に課金されるため、読み取るパーティションが減れば費用が直接下がり、クエリ実行前に処理バイト数を正確に見積もることもできます。パーティション分割に使えるのは、時間単位列(DATE / TIMESTAMP / DATETIME)、取り込み時間、整数範囲(INTEGER)の 3 種類だけです。
・クラスタリング:指定した列(最大 4 列)の値でテーブル内(パーティション内)のデータを並べ替えて格納し、その列でフィルタしたときに不要なブロックを読み飛ばす仕組みです。値の種類が非常に多い(カーディナリティが高い)列に向いています。
②問題文の要件の整理
・最も多いクエリ:イベント日付の範囲での絞り込み + ユーザー ID(UUID)でのフィルタ
・目的:クエリの費用とパフォーマンスの最適化
③正解の理由
日付範囲の絞り込みはイベント日付列のパーティション分割で粗く(確実に)行い、各パーティションの中をユーザー ID でクラスタ化して細かく絞り込む、というのが BigQuery の定石です。「時間軸はパーティション、高カーディナリティ列はクラスタ」と覚えておきましょう。パーティションとクラスタを組み合わせることで、日付範囲外のパーティションはまったく読まず、範囲内でも該当ユーザーのブロックだけを読むため、費用と性能の両方が最適化されます。
【誤りの選択肢】
A:UUID は STRING 型で値の種類が膨大です。BigQuery のパーティション分割は時間単位列・取り込み時間・整数範囲にしか対応しておらず、UUID 列ではパーティション分割できません(仮にできたとしても、パーティション数の上限をすぐに超えます)。また、最も多い条件である日付範囲をクラスタ列にすると、パーティションのような確実なスキャン範囲の限定ができません。
B:取り込み時間パーティションは「BigQuery にデータが取り込まれた時刻」で分割されます。アナリストが絞り込むのはイベントの発生日付であり、遅延到着やバックフィルで取り込み日時とイベント日付がずれると、イベント日付の範囲でパーティション プルーニングが効きません。
C:クラスタリングだけでもブロックの読み飛ばしで性能は改善しますが、パーティション分割のような確実なスキャン範囲の限定やクエリ前の正確な費用見積もりができません。日付範囲で頻繁に絞り込む本ケースでは、日付でパーティション分割する D の方が費用削減効果が大きく、パーティション単位の有効期限設定などの管理もしやすくなります。
【参考】
パーティション分割テーブルの概要クラスタ化テーブルの概要