入力データとデータソースの管理

入力データを評価するときは、必要な I/O を考慮してください。クエリで何バイト読み込むか。入力データの量を適切に制限しているか。データはネイティブの BigQuery ストレージと外部データソースのどちらにあるか。クエリによって読み取られるデータの量とデータのソースは、クエリのパフォーマンスとコストに影響します。

クエリプランの説明を参照して、クエリによって入力データがどのように読み取られるかを調べることができます。

次のベスト プラクティスは、入力データの制御とデータソースの選択に関するガイダンスを提供します。

射影の制御 - SELECT * を避ける

ベスト プラクティス: 射影を制御する - 必要な列のみを照会します。

射影とは、クエリによって読み取られる列の数のことです。列の射影が多すぎると、追加の(無駄な)I/O と実体化(書き込み結果)が発生します。

SELECT * はデータのクエリに最もコストがかかる方法です。SELECT * を使用すると、BigQuery はテーブル内のすべての列をフルスキャンします。

データのテストや探索には、SELECT * ではなく、いずれかのデータ プレビュー オプションを使用してください。

LIMIT 句を SELECT * クエリに適用しても、読み取られるデータの量には影響しません。テーブル全体のすべてのバイトの読み取りに対して課金され、クエリは無料枠割り当てに対してカウントされます。

代わりに、必要な列のみを照会します。たとえば、SELECT * EXCEPT を使用して、結果から 1 つ以上の列を除外します。

テーブル内のすべての列を対象とするものの、データのサブセットに対してのみクエリを実行する必要がある場合は、以下のことを検討してください。

  • 代わりに、宛先テーブルで結果を実体化し、そのテーブルを照会する。
  • テーブルを日付別に分割し、該当するパーティションをクエリします。たとえば、WHERE _PARTITIONDATE="2017-01-01" とすると、2017 年 1 月 1 日のパーティションのみがスキャンされます。

データのサブセットをクエリしたり SELECT * EXCEPT を使用したりすると、クエリで読み取られるデータの量を大幅に削減できます。コストの削減に加えて、データ I/O の量とクエリ結果に必要な実体化の量を減らすことで、パフォーマンスが向上します。

分割されたクエリを取り除く

ベスト プラクティス: 分割テーブルをクエリする場合は、_PARTITIONTIME 疑似列を使用してパーティションをフィルタリングします。

分割テーブルをクエリする場合は _PARTITIONTIME 疑似列を使用します。_PARTITIONTIME を使用すると、日付または日付の範囲を指定してデータをフィルタリングできます。たとえば、次の WHERE 句では、_PARTITIONTIME 疑似列を使って 2016 年 1 月 1 日から 2016 年 1 月 31 日までのパーティションを指定します。

WHERE _PARTITIONTIME
BETWEEN TIMESTAMP(“20160101”)
    AND TIMESTAMP(“20160131”)

このクエリは、日付範囲で指定されたパーティション内のデータのみを処理し、これによって入力データの量を減らせます。パーティションをフィルタリングすると、クエリのパフォーマンスが向上し、コストが削減されます。

可能な限りデータを非正規化する

ベスト プラクティス: BigQuery は、非正規化データの場合に最適です。スタースキーマやスノーフレーク スキーマなどのリレーショナル スキーマを保存するのではなく、データを非正規化して、ネスト フィールドと繰り返しフィールドを利用します。ネスト フィールドと繰り返しフィールドは、リレーショナル(正規化)スキーマを維持することによるパフォーマンスへの影響なしで、リレーションシップを維持できます。

最新のシステムでは、正規化データによるストレージ節約はあまり問題とはなりません。ストレージ コストが増加しても、データ非正規化によるパフォーマンス向上には価値があります。結合にはデータ調整(通信帯域幅)が必要です。非正規化するとデータがローカライズされて個々のスロットに入れられるため、並行実行が可能です。

データを非正規化しながらリレーションシップを維持する必要がある場合は、データを完全に平坦化するのではなく、ネスト フィールドと繰り返しフィールドを使用します。リレーショナル データが完全に平坦化されると、ネットワーク通信(シャッフル)がクエリのパフォーマンスを下げる可能性があります。

たとえば、ネスト フィールドと繰り返しフィールドを使用せずに orders スキーマを非正規化するには、order_id などのフィールドによるグループ化が必要になる場合があります(1 対多の関係がある場合)。シャッフルが行われるため、ネスト フィールドと繰り返しフィールドを使ってデータを非正規化するよりも、データをグループ化する方がパフォーマンスが低くなります。

場合によっては、データを非正規化し、ネスト フィールドと繰り返しフィールドを使用してもパフォーマンスが向上するとは限りません。以下のような場合は、非正規化を避けてください。

  • 頻繁にディメンションが変化するスタースキーマがある場合。
  • BigQuery は行レベルの変更(ミューテーション)があるオンライン トランザクション処理(OLTP)システムを補完しますが、それに置き換わることはできません。

ネストされたフィールドと繰り返しフィールドの使用

BigQuery は完全にフラットな非正規化を必要としません。ネストされたフィールドと繰り返しフィールドを使用して、リレーションシップを維持できます。

  • ネストデータ(STRUCT

    • ネストデータを使用すると、外部エンティティをインラインで表すことができます。
    • ネストデータを照会すると、リーフ フィールドを参照する「ドット」構文が使用されます。これは、結合を使用する構文に似ています。
    • ネストデータは、標準 SQL の STRUCTとして表されます。
  • 繰り返しデータ(ARRAY

    • モードを REPEATED に設定して RECORD 型のフィールドを作成すると、1 対多のリレーションシップをインラインで保持できます(リレーションシップのカーディナリティが高くない場合)。
    • 繰り返しデータでは、シャッフルは不要です。
    • 繰り返しデータは、ARRAY として表されます。繰り返しデータをクエリする際には、標準 SQL で ARRAY 関数を使用できます。
  • ネストされた繰り返しデータ(STRUCTARRAY

    • ネストと繰り返しは相互に補完します。
    • たとえば、トランザクション レコードのテーブルに STRUCT 項目の配列を含めることができます。

外部データソースを適切に使用する

ベスト プラクティス: クエリのパフォーマンスが最優先事項である場合は、外部データソースを使用しないでください。

BigQuery マネージド ストレージ内のテーブルのクエリは、通常、Google Cloud Storage や、Google ドライブ、Google Cloud Bigtable にある外部テーブルをクエリするよりもはるかに高速です。

次のような場合には、外部データソースを使用します。

  • データのロード時に抽出 - 変換 - 読み込み(ETL)オペレーションを実行する
  • 頻繁に変化するデータ
  • Cloud Bigtable からのデータの反復取り込みなどの定期的な読み込み

過剰なワイルドカード テーブルを避ける

ベスト プラクティス: ワイルドカード テーブルをクエリする場合は、できるだけ細かい接頭部を使用します。

ワイルドカードは、簡潔な SQL ステートメントを使用して複数のテーブルを照会するために使用します。ワイルドカード テーブルとは、ワイルドカード式に一致するテーブルが結合されたものです。ワイルドカード テーブルは、データセットに次のものが含まれている場合に便利です。

  • スキーマに互換性がある複数の類似した名前のテーブル
  • シャーディングしたテーブル

ワイルドカード テーブルをクエリする場合は、共通のテーブル接頭部の後にワイルドカード(*)を指定します。たとえば、FROM bigquery-public-data.noaa_gsod.gsod194* とすると、1940 年代のすべてのテーブルがクエリされます。

接頭部を細かく指定する方が、接頭部が短い場合よりパフォーマンスが優れています。たとえば FROM bigquery-public-data.noaa_gsod.gsod194* は、ワイルドカードに一致するテーブルが少ないので、FROM bigquery-public-data.noaa_gsod.* よりも優れています。

このページは役立ちましたか?評価をお願いいたします。

フィードバックを送信...

ご不明な点がありましたら、Google のサポートページをご覧ください。