マテリアライズド ビューを使用する

このドキュメントでは、マテリアライズド ビューとその使用方法について説明します。このドキュメントを読む前に、マテリアライズド ビューの概要マテリアライズド ビューの作成を理解しておいてください。

マテリアライズド ビューに対するクエリを実行する

通常のテーブルまたは標準ビューに対してクエリを行う場合と同じ方法で、マテリアライズド ビューに対してクエリを直接実行できます。マテリアライズド ビューに対するクエリは、マテリアライズド ビューが最後に更新されてからテーブルが変更されていても、常にビューのベーステーブルに対するクエリと一致します。クエリによって、マテリアライズド ビューの更新が自動的にトリガーされることはありません。

必要なロール

マテリアライズド ビューに対するクエリを実行するために必要な権限を取得するには、マテリアライズド ビューのベーステーブルとマテリアライズド ビュー自体に対する BigQuery データ閲覧者roles/bigquery.dataViewer)IAM ロールを付与するよう管理者に依頼してください。ロールの付与については、プロジェクト、フォルダ、組織へのアクセス権の管理をご覧ください。

この事前定義ロールには、マテリアライズド ビューに対するクエリを実行するために必要な権限が含まれています。必要とされる正確な権限については、「必要な権限」セクションを開いてご確認ください。

必要な権限

マテリアライズド ビューに対してクエリを実行するには、次の権限が必要です。

  • bigquery.tables.get
  • bigquery.tables.getData

カスタムロールや他の事前定義ロールを使用して、これらの権限を取得することもできます。

スマートな調整のメリットを得るためには、クエリに対するこれらの権限が必要です。

BigQuery での IAM ロールの詳細については、IAM の概要をご覧ください。

増分アップデート

BigQuery はキャッシュされたビューのデータを新しいデータと組み合わせて、引き続きマテリアライズド ビューを使用しながら一貫したクエリ結果を提供します。これは、単一テーブルのマテリアライズド ビューの場合、最後の更新以降にベーステーブルが変更されていないか、新しいデータのみが追加された場合に可能です。JOIN ビューでは、JOIN の左側にあるテーブルにのみデータを追加できます。JOIN の右側にあるテーブルのいずれかが変更されている場合、ビューを増分更新できません。

最後の更新以降にベーステーブルの更新または削除が行われた場合、または JOIN の右側にあるマテリアライズド ビューのベーステーブルが変更された場合、BigQuery は自動的に元のクエリに戻ります。結合とマテリアライズド ビューの詳細については、結合をご覧ください。更新や削除が実行される原因となる Google Cloud コンソール、bp コマンドライン ツール、API のアクションの例を次に示します。

  • データ操作言語(DML)UPDATEMERGEDELETE ステートメント
  • 切り捨て
  • パーティションの有効期限

次のメタデータ オペレーションでも、マテリアライズド ビューが段階的に更新されることはありません。

  • パーティションの有効期限の変更
  • 列の更新または削除

マテリアライズド ビューを段階的に更新できない場合、ビューが自動または手動で更新されるまで、そのキャッシュ内のデータはクエリで使用されません。ジョブでマテリアライズド ビューデータが使用されなかった理由の詳細については、マテリアライズド ビューが拒否された理由を理解するをご覧ください。また、ベーステーブルにテーブルのタイムトラベル間隔を超える期間の未処理の変更が蓄積されている場合、マテリアライズド ビューは増分更新できません。

パーティションの配置

マテリアライズド ビューがパーティショニングされている場合、BigQuery ではそのパーティションがベーステーブルのパーティショニング列のパーティションと確実に連携するように変更されます。連携とは、ベーステーブルの特定のパーティション データが、マテリアライズド ビューの同じパーティションに関係することを意味します。たとえば、ベーステーブルのパーティション 20220101 の行は、マテリアライズド ビューのパーティション 20220101 のみに関係します。

マテリアライズド ビューがパーティショニングされている場合、増分更新で説明する動作は、個別のパーティションごとに発生します。たとえば、ベーステーブルの 1 つのパーティションでデータが削除された場合でも、BigQuery は引き続きマテリアライズド ビューの他のパーティションを使用できます。

内部結合を持つマテリアライズド ビューは、そのベーステーブルの 1 つにのみ連携できます。連携していないベーステーブルの 1 つが変更されると、ビュー全体に影響します。

スマートな調整

BigQuery は、可能な限りマテリアライズド ビューを使用するようにクエリを自動的に書き換えます。自動書き換えによってクエリのパフォーマンスと費用が改善します。また、クエリの結果は変更されません。クエリによって、マテリアライズド ビューの更新が自動的にトリガーされることはありません。クエリを書き換えるには、マテリアライズド ビューが次の条件を満たす必要があります。

  • そのベーステーブルの 1 つと同じデータセットに属している
  • クエリと同じベーステーブルのセットを使用している
  • 読み取るすべての列が含まれている
  • 読み取るすべての行が含まれている

スマートな調整の例

次のマテリアライズド ビュークエリの例を考えてみましょう。

SELECT
  store_id,
  CAST(sold_datetime AS DATE) AS sold_date
  SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE
  CAST(sold_datetime AS DATE) >= '2021-01-01' AND
  promo_id IS NOT NULL
GROUP BY 1, 2

次の例に、クエリと、このビューを使用してクエリが自動的に書き換えられる(または書き換えられない)理由を示します。

クエリ 書き換え? 理由
SELECT
SUM(net_paid) AS sum_paid,
SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE
CAST(sold_datetime AS DATE) >= '2021-01-01' AND
promo_id IS NOT NULL
× ビューには、読み取られるすべての列を含める必要があります。ビューに「SUM(net_paid)」は含まれません。
SELECT SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE
CAST(sold_datetime AS DATE) >= '2021-01-01' AND
promo_id IS NOT NULL
SELECT SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE
CAST(sold_datetime AS DATE) >= '2021-01-01' AND
promo_id IS NOT NULL AND
customer_id = 12345
× ビューには、読み取られるすべての列を含める必要があります。ビューには「customer」は含まれません。
SELECT SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE
sold_datetime= '2021-01-01' AND
promo_id IS NOT NULL
× ビューには、読み取られるすべての列を含める必要があります。「sold_datetime」は出力ではありません(ただし、「CAST(sold_datetime AS DATE)」は有効です)。
SELECT SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE
CAST(sold_datetime AS DATE) >= '2021-01-01' AND
promo_id IS NOT NULL AND
store_id = 12345
SELECT SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE
CAST(sold_datetime AS DATE) >= '2021-01-01' AND
promo_id = 12345
× ビューには、読み取られるすべての行を含める必要があります。「promo_id」は出力ではないため、より制限の厳しいフィルタはビューに適用できません。
SELECT SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE CAST(sold_datetime AS DATE) >= '2020-01-01'
× ビューには、読み取られるすべての行を含める必要があります。ビューフィルタは 2021 年以降の日付をフィルタリングしますが、クエリは 2020 年以降の日付を読み取ります。
SELECT SUM(net_profit) AS sum_profit
FROM dataset.store_sales
WHERE
CAST(sold_datetime AS DATE) >= '2022-01-01' AND
promo_id IS NOT NULL

クエリが書き換えられたかどうかを確認する

スマートな調整によって、マテリアライズド ビューを使用するようにクエリが書き換えられたかどうかを確認するには、クエリプランを調べます。クエリが書き換えられた場合、クエリプランには READ my_materialized_view ステップが含まれます。ここで、my_materialized_view は使用されるマテリアライズド ビューの名前です。クエリでマテリアライズド ビューが使用されなかった理由を確認するには、マテリアライズド ビューが拒否された理由を確認するをご覧ください。

マテリアライズド ビューが拒否された理由を確認する

マテリアライズド ビューの自動更新を無効にしていて、テーブルに未処理の変更がある場合、クエリは数日間は高速になる可能性がありますが、その後は元のクエリに戻り、処理速度が低下します。マテリアライズド ビューのメリットを活用するには、自動更新を有効にするか、定期的に手動で更新し、マテリアライズド ビューの更新ジョブをモニタリングして、成功を確認します。

マテリアライズド ビューが拒否された理由を確認する方法は、使用したクエリの種類によって異なります。

  • マテリアライズド ビューの直接クエリ
  • スマートな調整によってマテリアライズド ビューの使用が選択される間接的なクエリ

以降のセクションでは、マテリアライズド ビューが拒否された理由を確認するための手順を説明します。

マテリアライズド ビューの直接クエリ

マテリアライズド ビューの直接クエリでは、特定の状況においてキャッシュされたデータが使用されない場合があります。マテリアライズド ビューデータが使用されなかった理由を確認する手順は、次のとおりです。

  1. マテリアライズド ビューの使用状況のモニタリングの手順に沿って、クエリの materialized_view_statistics フィールドでターゲットのマテリアライズド ビューを見つけます。
  2. chosen が統計値に存在し、その値が TRUE の場合、マテリアライズド ビューがクエリで使用されています。
  3. rejected_reason フィールドを確認して、次のステップを確認します。ほとんどの場合、マテリアライズド ビューを手動で更新するか、次の自動更新を待ちます。

スマートな調整を使用したクエリ

  1. マテリアライズド ビューの使用状況のモニタリングの手順に沿って、クエリの materialized_view_statistics でターゲットのマテリアライズド ビューを見つけます。
  2. rejected_reason を確認して、次のステップを確認します。たとえば rejected_reason 値が COST の場合、スマートな調整によって、コストとパフォーマンスがより効率的なデータソースが特定されています。
  3. マテリアライズド ビューが存在しない場合は、マテリアライズド ビューの直接クエリを試し、マテリアライズド ビューの直接クエリの手順を行います。
  4. 直接クエリがマテリアライズド ビューを使用しない場合、マテリアライズド ビューの形状はクエリと一致しません。スマートな調整の詳細と、マテリアライズド ビューを使用したクエリの書き換え方法については、スマートな調整の例をご覧ください。

よくある質問

スケジュールされたクエリとマテリアライズド ビューを使用するのはどのような場合ですか?

スケジュールされたクエリは、複雑な計算を何かしらの形で定期的に実行する際に便利です。クエリは実行されるたびに完全に実行され、以前の結果は使用されません。クエリのコンピューティング費用はすべて支払う必要があります。最新のデータを必要とせず、データが未更新であることが問題にならない場合は、スケジュールされたクエリが最適です。

マテリアライズド ビューは、以前に計算された結果を再利用してレイテンシとコストを最小限に抑えつつ、最新のデータをクエリする必要がある場合に最適です。マテリアライズド ビューを疑似インデックスとして使用して、既存のワークフローを更新せずにベーステーブルに対するクエリを高速化できます。--max_staleness オプションを使用すると、マテリアライズド ビューの許容可能な未更新状態を定義できます。頻繁に変更される大規模なデータセットを処理するときに、コストを抑えながら一貫して高いパフォーマンスを実現できます。

一般的なガイドラインとして、可能な限り、また、複雑な計算を何かしらの形で実行しない場合は、マテリアライズド ビューを使用してください。

マテリアライズド ビューに対する一部のクエリが手動のマテリアライズド テーブルに対する同じクエリよりも低速です。これはなぜですか?

一般に、マテリアライズド ビューに対するクエリのパフォーマンスは、同等のマテリアライズド テーブルに対するクエリと同じであるとは限りません。これは、マテリアライズド ビューは常に新しい結果を返すことが保証されており、前回のビュー更新以降にベーステーブルの変更を考慮する必要があるためです。

次のシナリオを見てみましょう。

CREATE MATERIALIZED VIEW my_dataset.my_mv AS
SELECT date, customer_id, region, SUM(net_paid) as total_paid
FROM my_dataset.sales
GROUP BY 1, 2, 3;

CREATE TABLE my_dataset.my_materialized_table AS
SELECT date, customer_id, region, SUM(net_paid) as total_paid
FROM my_dataset.sales
GROUP BY 1, 2, 3;

たとえば、次のクエリについて考えます。

  SELECT * FROM my_dataset.my_mv LIMIT 10
通常、このクエリは次のクエリよりもずっと遅くなります。
  SELECT * FROM my_dataset.my_materialized_table LIMIT 10
常に最新の結果を提供するために、BigQuery では、「LIMIT 10」という述語を適用する前に、ベーステーブルの新しい行をクエリしてマテリアライズド ビューに結合する必要があります。そのため、マテリアライズド ビューが完全に最新の状態であっても、速度は低いままです。

一方、マテリアライズド ビューに対する集計は、通常、マテリアライズド テーブルに対するクエリと同じ速さです。たとえば、次の例をご覧ください。

  SELECT SUM(total_paid) FROM my_dataset.my_mv WHERE date > '2020-12-01'
このクエリは、以下と同じ速度です。
  SELECT SUM(total_paid) FROM my_dataset.my_materialized_table WHERE date > '2020-12-01'