BigQuery の仕組み: パフォーマンスを強化するサーバーレス ストレージとクエリ最適化の舞台裏
Google Cloud Japan Team
※この投稿は米国時間 2023 年 3 月 18 日に、Google Cloud blog に投稿されたものの抄訳です。
BigQuery が顧客から支持されているのは、難しいことを簡単に行えるという点です — BigQuery Machine Learning (BQML) SQL であれば、データ アナリストはデータ サイエンティストとしての役割を担えますし、SEARCH 機能を使用したリッチテキスト分析で、非構造化データに対するアドホック テキスト検索を活用できるようになります。BigQuery の使いやすさの主な理由のひとつに、BigQuery の基盤となるサーバーレス アーキテクチャがあります。これにより、分析クエリを強化するとともに、クエリ実行のスピードを経時的に改善することが可能で、しかも SQL のコードに変更をまったく加える必要がありません。
このブログでは、ストレージやクエリの最適化、エコシステムの改善など、BigQuery のサーバーレス アーキテクチャの舞台裏をお見せして、その秘密についてご紹介します。また、こうした点により、どのようにしてお客様が制約に縛られることなくデータ分析、データ エンジニアリング、データ サイエンスのワークロードを実行できるようになるのかについても説明します。
ストレージ最適化
状況適応型のストレージ ファイル サイジングでクエリのパフォーマンスを改善する
BigQuery では、Capacitor と呼ばれるカラム型ファイルストアにテーブルデータが保存されます。この Capacitor ファイルのサイズは当初は固定(数百 MB 規模)で、BigQuery のお客様の大規模なデータセットに対応できるサイズでした。ファイルのサイズが大きく、クエリがスキャンする必要があるファイルの数を減らせるため、ペタバイト規模のデータのクエリを高速かつ高効率で実行できました。ただし、従来型のデータ ウェアハウスから移行する顧客は小規模なデータセット(GB、TB 規模)を取り込むようになってきており、デフォルトの「大きい」ファイルサイズはそのような小規模なテーブルにとっては最適なフォーム ファクタではなくなります。このように、大小さまざまなクエリ ワークロードを扱うユーザーに合わせてソリューションをスケーリングできるようにする必要があるため、BigQuery チームは、状況に応じて Capacitor ファイルのサイズを変更して小規模なクエリのパフォーマンスを改善する、状況適応型のファイル サイジングというコンセプトを考案しました。
BigQuery チームは、BigQuery ストレージで作成される新しいテーブルに適切なファイルサイズ(数十~数百 MB の範囲)を動的に割り当てるアダプティブ アルゴリズムを開発しました。既存のテーブルに関しては、ファイルサイズが「固定」の既存のテーブルを状況適応型のテーブルに徐々に移行する、つまり、お客様の既存のテーブルをパフォーマンスに優れた状況適応型のテーブルに移行するバックグラウンド プロセスを追加しました。今では、バックグラウンドの Capacitor プロセスがすべてのテーブルの拡大を継続的にスキャンして、サイズ変更を動的に実行するようになっているため、最適なパフォーマンスを実現できます。
「本番環境において、実行に 1 分以上かかる分析クエリの数が 90% 以上減少しました。」 - Wayfair、データアクセスおよび可視化プラットフォーム担当アソシエイト ディレクター、Emily Pearson 氏
パフォーマンスを強化する大規模メタデータ
すべてのテーブルのすべてのファイルをワークロードでスキャンしなければならない場合、ストレージ ファイルで保持された BigQuery テーブルからの読み取りやそのような BigQuery テーブルへの書き込み操作が即座に非効率的になる可能性があります。BigQuery では、ほとんどの大規模なデータ処理システムと同様に、ファイルの内容に関する豊富な情報が蓄積されており、これは各 Capacitor ファイルのヘッダーに保存されます。データに関するこの情報はメタデータと呼ばれます。BigQuery でのクエリの計画、ストリーミング、バッチ取り込み、トランザクション処理などの読み取りおよび書き込みプロセスで、必要なオペレーションの実行対象ストレージ内にある関連ファイルを迅速に特定できるようになるため、関連性のないデータファイルの読み取りで時間を無駄にすることがなくなります。
ただし、小規模なテーブルのメタデータの読み取りは比較的単純で時間がかからないものの、大規模(ペタバイト規模)ファクト テーブルの場合、数百万単位のメタデータ エントリが生成されることがあります。そのようなクエリで結果を迅速に生成するには、クエリ最適化機能に高性能のメタデータ ストレージ システムが必要です。
2021 年の VLDB の論文「Big Metadata: When Metadata is BigData」で提唱された考え方に基づいて、BigQuery チームは、CMETA という分散型のメタデータ システムを開発しました。その特徴は、きわめて大規模なテーブルに対応できる、きめ細かい列とブロックレベルのメタデータであり、このメタデータが 1 つのシステム テーブルとして整理され、アクセス可能な状態になります。クエリ最適化機能がクエリを受け取ると、CMETA システム テーブルとのセミ結合(WHERE EXISTS または WHERE IN)を適用するようにそのクエリの再書き込みを実行します。メタデータのデータ ルックアップをクエリ述部に追加することで、クエリの効率が著しく改善されます。
BigQuery の Capacitor ベースのストレージのメタデータを管理することとは別に、CMETA が BigLake を介して外部テーブルにも拡張されるため、大量の Hive パーティション分割テーブルのルックアップのパフォーマンスが改善されます。
VLDB の論文で公開されている結果によれば、100GB~10TB のテーブルに対するクエリの場合で CMETA メタデータ システムを使用すると、クエリの実行時間が 5 倍から 10 倍に加速されます。
ストレージ データ最適化の 3 つの C: コンパクト(compact)、統合(coalesce)、クラスタ(cluster)
BigQuery には、Capacitor 内のストレージ ファイルに保存されたデータを継続的に分析して最適化する組み込みのストレージ最適化機能があり、次のようなさまざまな手法が使用されます。
コンパクト(compact)、統合(coalesce): BigQuery は、SQL や API インターフェースを使用するファスト INSERT に対応しています。データが初めてテーブルに挿入されるときに、その挿入のサイズによっては、きわめて多数の小規模なファイルが作成されることがあります。ストレージ最適化機能はこのような個々のファイルを 1 つに統合して、メタデータのオーバーヘッドを増やすことなくテーブルデータが効率的に読み取られるようにします。
テーブルデータの保存に使用されるファイルの中には、時間の経過に伴いサイズが適切ではなくなるものがあります。ストレージ最適化機能がこのデータを分析して、適切なサイズのファイルへの書き込みを再度実行します。これにより、適切な数のファイルをクエリでスキャンできるようになり、データの取得が最も効率的になります。なぜ適切なサイズが重要なのでしょうか?ファイルが大きすぎる場合、その大きなファイルから不要な行を除去する際のオーバーヘッドが生じます。ファイルが小さすぎる場合、大量の読み取り対象の小規模ファイルのメタデータの読み取りと管理のオーバーヘッドが生じます。
クラスタ(cluster): ユーザー定義の列並べ替え順があるテーブルは、クラスタ化された列と呼ばれます。複数の列で 1 つのテーブルをクラスタ化すると、BigQuery によるデータの並べ替えとストレージ ブロックへのグループ化が実行される際に、どの列が優先されるかが列の順序に基づいて決定されます。BigQuery クラスタ化では、クラスタ化列でフィルタや集計を行うクエリを高速化します。これは、テーブルやテーブル パーティション全体ではなく、クラスタ化列に基づいて関連する関連ファイルとブロックのみをスキャンすることで実現されます。クラスタ化されたテーブル内でデータが変更されると、BigQuery ストレージ最適化機能が自動的に再クラスタ化を実行します。これにより、クラスタの定義が継続的に更新され、一貫性の高いクエリ パフォーマンスが確保されるようになります。
クエリの最適化
スキュー処理を結合してデータ分析の遅延を減らす
BigQuery でクエリの実行が開始されると、クエリ最適化機能がクエリを実行グラフに変換して、いくつかのステージに分割します(それぞれのステージは複数のステップで構成されます)。BigQuery は、異なるデータサイズやキーの分散に応じて実行計画が動的に進展する動的クエリ実行を使用して、クエリのレスポンス時間の短縮と効率的なリソースの割り当てを実現しています。大規模なファクト テーブルにクエリを実行する場合、データのスキューが存在している可能性がきわめて高くなります。これはつまり、特定のキーでのデータの分散が非対称的で、データの不均一な分散が生じることを意味します。そのため、スキューがあるファクト テーブルに対してクエリを実行する場合、通常のデータの場合と比較して、スキューがあるデータに対応するレコードに発展する可能性が高いです。クエリエンジンが作業をワーカーに分配してスキューのあるテーブルをクエリする場合に、いずれかのワーカーで作業の完了までにかかる時間が相対的に遅くなることがあります。これは、特定のキー値での余分な行(スキュー)があるためで、ワーカーごとの処理時間の不均一につながります。
分散に偏りがあるデータについて考えてみましょう。クリケットは、国際的なチームスポーツです。ただし、クリケットは世界の特定の国でのみ人気があります。クリケットのファンの一覧を国ごとに管理する場合、データが国際クリケット評議会の正式な加盟国出身のファンに偏ることになり、すべての国で均一に分散されなくなります。
従来型のデータベースの場合、データ分散戦略を維持することで、このような事態に対処しようとします。ただし、昨今のデータ ウェアハウスの場合、データの分散のされ方は目まぐるしく変化します。また、データ アナリストが実行するクエリの複雑さがさらに増していくこともありえるため、統計情報が古くなり、その有用性が低下することになります。スキューは結合の左側または右側で参照されるテーブル列に存在する可能性があり、これは、結合列でクエリされるテーブルによります。
BigQuery チームは、結合スキュー処理の手法を開発することで、データのスキューに対応しました。これは、データスキューを検出して作業を比例的に配分することで、より多くのワーカーを分配してスキューのあるデータの結合を処理できるようにするためのものです。結合の処理と同時に、クエリエンジンがスキューのあるデータの結合入力のモニタリングを継続します。スキューが検出されると、クエリエンジンがそのスキューのあるデータの結合を処理するように計画が変更されます。このクエリエンジンが、スキューのあるデータをさらに分割して、スキューのあるデータとないデータで処理が均一に分散されるようにします。これにより、データスキューのあるテーブルのデータを処理するワーカーが、検出されたスキューに応じて実行時に比例的に配分されるようになります。すべてのワーカーが同時に作業を完了できるようになり、スキューのあるデータが原因で発生する待機時間によって発生する遅延がなくなるため、クエリ実行時間の加速に貢献します。
「データ処理の自動化で BigQuery を採用することは簡単で、このことには驚かされました。私たちは、クエリの最適化を自身で行う必要がありません。そのようなことをせずに、クエリを生成し、そのクエリを BigQuery に読み込み、数秒後に結果を取得するプログラムを作成できます。」 - AZ Delta、最高情報責任者、Peter De Jaeger 氏
キューを利用した動的同時実行
BigQuery のクエリジョブの割り当てと上限のドキュメントには、「プロジェクトで同時インタラクティブ クエリを最大 100 まで実行できます。」という記載があります。これまで BigQuery ではデフォルトの同時接続数の上限が 100 に設定されており、お客様の 99.8% ワークロードの要件に対応できていました。これはソフトリミットであったため、管理者は、同時接続数の上限をリクエスト プロセスを介していつでも引き上げることが可能でした。データ エンジニアリング、複雑な分析、Spark や AI/ML の処理など、かつてないほどに拡大するワークロードの幅に対応できるようにするために、BigQuery チームは、クエリのキューを利用する動的同時実行を開発しました。これにより、同時接続数に関する実質的なすべての上限が取り除かれ、管理上の負担が軽減されます。クエリのキューを利用する動的同時実行には、以下の機能があります。
動的同時実行の最大数の設定: 目標同時実行をゼロに設定している場合、動的同時実行の利点をデフォルトで活用できます。BigQuery が、予約のサイズと使用のパターンに基づいて同時実行の設定と管理を自動的に行います。経験のある管理者による手動によるオーバーライドを行えるようにする必要がある場合は、目標同時実行の上限を設定します(これは、動的同時実行の設定を上書きするものです)。目標同時実行の上限は予約で利用可能なスロット数の関数であり、管理者が指定する上限がこれを超えることはできません。オンデマンド ワークロードの場合、この上限が動的に計算され、管理者による設定は行えません。
同時実行の上限を超える数のクエリをキューに入れる: ピーク時のワークロードでクエリの急増が発生して、同時実行の最大数の上限を超えるオーバーフロー シナリオに対応できる Query Queues がサポートされるようになりました。Query Queues を有効にすると、BigQuery では、最大で 1,000 のインタラクティブ クエリをキューに入れられるようになります。そのため、以前のように同時実行の上限により停止するのではなく、実行のスケジュールが設定されるようになりました。今では、アイドル期間や使用量が少ない期間にスキャンを行う必要がないため、ワークロードのリクエストを送信するタイミングを最適化できます。BigQuery が、リクエストを自動的に実行するか、現在実行中のワークロードが完了するとすぐに実行するようにキューにスケジュールします。Query Queues の詳細については、こちらをご覧ください。
「BigQuery は、非常に短くて非常に複雑なクエリにおいて特にパフォーマンスが優れています。BigQuery では、テストしたクエリの半分(47%)が 10 秒未満で完了できたのに対し、代替ソリューションではわずか 20% でした。さらに詳しく言うと、テストした数千のクエリのうち、BigQuery での実行で 2 分以上かかったクエリはわずか 5% であるのに対し、代替ソリューションでは約半分(43%)が完了に 2 分以上かかりました。」 - Yahoo!、エンジニアリング担当シニア ディレクター、Nikhil Mishra 氏
データを迅速かつ効率的に提供するための Colossus Flash Cache
ほとんどの分散型処理システムでは、費用(ハードディスク上のデータに対するクエリ)とパフォーマンス(メモリ内のデータに対するクエリ)のトレードオフを考慮する必要があります。BigQuery チームは、このトレードオフは実際には誤った考えであり、どちらかを選ぶのではなく、低コストと高パフォーマンスを同時に実現できると考えています。これを実現するために、Colossus Flash Cache という、頻繁にクエリされるデータ用のフラッシュ ストレージにキャッシュを保持する分散型の中間キャッシュ レイヤを開発しました。アクセス パターンに基づいて、基盤のストレージ インフラストラクチャがデータを Colossus Flash Cache に保存します。このようにすることで、クエリの実行でディスクにアクセスしてデータを取得する必要はほとんどなくなります。データは、Colossus Flash Cache から迅速かつ効果的に提供されます。
余計なリソース使用を回避するための最適化された Shuffle
BigQuery では、クエリのメモリ内実行を利用してスケーラビリティに優れたデータ処理機能を実現しています。このようなメモリ内オペレーションでは、ディスクからデータを取得し、クエリ処理の各段階の中間結果を Shuffle と呼ばれる別のメモリ内分散コンポーネントに保存します。共通テーブル式(CTE)を含む WITH 句がある分析クエリは、多くの場合、複数のサブクエリで同じテーブルを参照します。BigQuery チームはこれを解決するために、重複 CTE 検出メカニズムをクエリ最適化機能に組み込みました。このアルゴリズムは、リソースの使用量を大幅に減らせるため、クエリで共有できる Shuffle のキャパシティを増強できます。
また、Shuffle の使用状況をより把握できるようにするために、PERIOD_SHUFFLE_RAM_USAGE_RATIO 指標を JOBS INFORMATION_SCHEMA ビューと Admin Resource チャートに追加しました。このような改善により、Resource Exceeded のエラーの数は少なくなるはずです。また、追跡指標が利用できるようになったため、余計な Shuffle リソースの使用を防止するための予防的アクションを実行できるようになっています。
「私たちのチームでは、データを活用してさまざまなことを行い、優れたプロダクトやサービスを構築したいと考えていましたが、当時使用していたテクノロジー ツールではその試みを行うことができませんでした。そして、そのようなデータは継続的に増加していきました。2014 年から 2018 年までの期間で、300% 拡大したデータ ウェアハウスもあります。クラウドへ移行する場合は通常、リエンジニアリングかリフト&シフトのいずれかになりますが、私たちは、移行して改良という異なる戦略を採用しました。BigQuery の容量や弾力性など、BigQuery の能力を最大限活用できたため、容量の制約という本質的な課題を解決できました。」 - HSBC、データ サービス エンジニアリング担当デリバリー責任者、Srinivas Vaddadi 氏
エコシステムの最適化
より高速な取り込み、より高速な外向きトラフィック、より高速な連携
BigQuery のユーザーが達成できるパフォーマンスの改善は、BigQuery のクエリエンジンのみに限られたことではありません。BigQuery を別のクラウド サービスと連携させて、データ アナリストが別のデータソースからのデータの取り込みや、別のデータソースへのクエリの実行を、BigQuery データと連携させて行えるようにしているお客様もいるかと思います。相互運用性をさらに改善するために、BigQuery チームは他のクラウド サービスと密に連携して、さまざまな統合に取り組んでいます。
BigQuery JDBC/ODBC ドライバ: ODBC / JDBC ドライバの新しいバージョンで、認証トークンの更新がバックグラウンドで処理されるようになり、OAuth 2.0(OAuthType=1)を使用するより高速なユーザー アカウント認証がサポートされるようになりました。
BigQuery と Bigtable: Cloud Bigtable と BigQuery の連携の一般提供が開始され、特定の行キーのクエリのプッシュダウンがサポートされるようになり、テーブルを完全にスキャンする必要性がなくなりました。
BigQuery と Spanner: BigQuery で Spanner に対して実行される連携クエリで、実行の優先順位を指定できるようになりました。これにより、連携クエリが高い優先度で実行された場合にトランザクション トラフィックと競合させるかどうかや、低い優先度の設定の場合に完了できるかどうかを指定できます。
BigQuery と Pub/Sub: BigQuery で、専用設計の「BigQuery サブスクリプション」を介して Pub/Sub イベントを直接取り込めるようになり、イベントを BigQuery テーブルに直接書き込めるようになりました。
BigQuery と Dataproc: BigQuery 用の Spark コネクタが、BigQuery Storage Write API を使用した DIRECT 書き込みメソッドをサポートするようになり、データを Cloud Storage に書き込む必要性がなくなりました。
BigQuery で何ができるか?
まとめますと、このような BigQuery に加えられる改善が、実際のパフォーマンス上の成果、そして、世界中のお客様のビジネス上の利益につながります。たとえば、Camanchaca はデータ処理の時間を 6 倍短縮しました。Telus は、データ処理の時間を 20 倍短縮して 500 万ドルの費用を削減しました。さらに、Vodafone はデータ運用とエンジニアリングにかかる費用の 70% の削減を達成し、Crux は読み込み時間の 10 倍の短縮を達成しました。
「きわめて高速かつ効果的にデータの BigQuery への読み込みができるため、プロダクトの構築をさらに行えるようになりました。効率性も改善され、付加価値の高いサービスも実現できるようになりました。ツールキットの一環として BigQuery を活用することで、顧客の課題の解決に貢献するプロダクトをさらに考案できるようになります。」 - Crux、インフラストラクチャおよびオペレーション責任者、Ryan Haggerty 氏
BigQuery を活用して、ご自身のビジネスで同様の成果を出す方法に関して興味がおありですか?Data Cloud and AI Summit ‘23 に参加して、BigQuery の最新情報をご覧ください。また、サーバーレスの力を活用したパフォーマンス イノベーションのロードマップに関してもぜひご確認ください。