Google BigQuery の隠れた名機能
Google Cloud Japan Team
※この投稿は米国時間 2022 年 8 月 4 日に、Google Cloud blog に投稿されたものの抄訳です。
BigQuery は驚異的です。Google Cloud の中でも、好きなツールの一つです。幸いなことに、Google も同じように感じているようで、新機能の追加を継続しています。BigQuery ファンには、喜ばしいことです。
どんなに長く BigQuery を使ってきても、時折新しい発見があります。本日は、次の 4 点についてお伝えしたいと思います。
AUTO カラム
マルチステートメント トランザクション
クラスタリング
インデックス
私個人の意見ですが、これらはドキュメントや講演で十分に注目されていない優れた機能です。
AUTO カラム
これはまさに「隠れた名機能」です。この機能について、公式ドキュメントでは確認できません(少なくとも、私は見つけられませんでした)。Google Issue Tracker で触れられているだけです。
データを BigQuery に push した後、別のシステムでスケジュールされたジョブを実行して、新着データを処理したいとします。たとえば、システムが BigQuery から別のストレージにデータを pull しようとする場合や、このシステムがデータに基づいて、1 時間ごとにレポートを実行する必要がある場合などです。いずれの場合でも、同じレコードを複数回処理することは避けたいでしょう。その結果、どのレコードが処理済みで、どのレコードが処理後に追加されたか把握する方法が必要となります。
従来の OLTP DB とは異なり、BigQuery は自動増分列または現在の日時が自動的に入力される列をサポートしていません。これは、ストリーミング API と AUTO 機能を使用していない場合に当てはまります。後者の場合、テーブル スキーマに TIMESTAMP 列を追加し、JSON ペイロードに「AUTO」を割り当てることができます。これにより、BigQuery は、レコードが BigQuery にいつ到達したか示すタイムスタンプを前述の列に自動入力できるようになります。
マルチステートメント トランザクション
BigQuery は OLTP DB ではありませんが、マルチステートメント トランザクションをサポートしています。
技術的に言えば、この投稿を書いている時点では、マルチステートメント トランザクションはプレビュー段階ですが、この機能が間もなく一般提供になることを願っています。
おそらく、トランザクションが何で、どのように使用できるか説明する必要はないでしょう。マルチステートメント トランザクションの詳細は、公式ドキュメントでご確認いただけます。
しかしながら、注目すべき興味深い点がいくつかあります。
トランザクションがテーブル内の行を変更(更新または削除)する場合、同じテーブル内の行を変更する別のトランザクション、または DML ステートメントは同時に実行できません。競合するトランザクションは、キャンセルされます。
トランザクションでは、永続的なエンティティに影響する DDL ステートメントを使用できません。
CURRENT_TIMESTAMP、CURRENT_DATE、CURRENT_TIME 関数は、トランザクション開始時刻のタイムスタンプを返します。
FOR SYSTEM_TIME AS OF 句を使用して、トランザクション開始時刻のタイムスタンプを超えてテーブルを読み取ることはできません。このような操作を行うと、エラーが返されます。
トランザクション内で、マテリアライズド ビューは論理ビューとみなされます。トランザクション内のマテリアライズド ビューにクエリを実行できますが、同等の論理ビューと比べてパフォーマンスが改善することも、コストが削減されることもありません。
クラスタリング
BigQuery でのクエリの最適化(BigQuery の場合、主にコストの最適化に関するもの)となると、思い浮かぶ最初のアプローチは、テーブル パーティショニングです。
テーブル シャーディングについても、聞いたことがあるかもしれません。では、シャーディングとパーティショニングについて少し説明しましょう。テーブル パーティショニングに関する情報は、公式ドキュメントでご確認いただけます。テーブル シャーディングについては、パーティショニング ドキュメントのパーティショニングとシャーディングのセクションを除いて、どこにも説明がありません。これは、シャーディングがレガシーとなった機能であり、デフォルトでは、パーティショニングの使用が必要となっていることを暗示しています。
しかし、利用可能なオプションは、パーティショニングだけではありません。クラスタリングもあります。パーティショニングでは、データがパーティションに分割されますが(必要に応じて、クエリが特定のパーティションのみを読み取れるようにする)、クラスタリングは、関連するデータを同じ場所に配置し、クラスタリング列のフィルタが使用されている場合に、クエリがデータの特定のセグメントにアクセスできるようにすることで機能します。
では、パーティショニングとクラスタリングではどちらが良いのでしょうか?
最初に、このトピックに関する公式ドキュメントがあります。このドキュメントで、たくさんの役立つ推奨事項をご確認いただけます。
次に、パーティショニングは、時間単位列と整数列、および取り込み時間に基づいてのみ可能であるので注意してください。
クラスタリングは、BOOL、GEOGRAPHY、STRING など、他のタイプを数多くサポートしています。さらに、クラスタリングは、最大 4 列のグループをサポートしています。最後に、両方使用したらどうでしょうか?パーティショニングとクラスタリングの両方を同じテーブルの同じフィールドまたは異なるフィールドに適用できます。
クラスタリングは、インデックスと同じではないことに注意することが重要です(インデックスについては、後で詳しくお話しします)。特定のフィールドをベースにしたクラスタリングの適用は、ポイント検索を意味するものではありません。レコードがまとめてクラスタ化され、特定のクラスタのクエリにのみ課金されるということを単に意味しています。
クラスタの大きさはどれくらいでしょうか?ドキュメントでは、明示されていません。同じフィールドをベースにしたパーティショニングとクラスタリングの両方を使用する場合、もちろん、各クラスタがそれぞれのパーティションを超えることはありません。ただし、パーティションが小さい場合、各パーティションは 1 つのクラスタでのみ構成されることが多いです。その結果、クラスタリングのメリットは見られません。
大小のパーティションのしきい値は何でしょうか?ドキュメントに基づくと、約 1 GB のようです。テーブル全体(または各パーティション)がそれよりも小さい場合、おそらく、クラスタリングからのメリットはないでしょう。
インデックス
これは、現在プレビュー段階にある、もう一つの驚異的な機能です。公式ドキュメントは、こちらです。
名前から察しがつくように、ポイント検索向けに設計されていますが、任意のフィールドを対象とするものではありません。現在は、インデックスを使用することで、非構造化テキスト、または半構造化 JSON データに埋め込まれている一意のデータ要素を簡単に見つけることができます。
インデックスは、SEARCH クエリを実行する場合にのみ使用されます。
指定したフィールドのリストに対するインデックスを作成できます。ALL FIELDS も指定できます。これにより、テーブル内のすべての STRING または JSON データにインデックスが作成されます。
インデックスの作成方法に関係なく、SEARCH 関数により柔軟性が高まり、各特定のクエリに関与する特定のフィールドの選択(または除外)が可能になります。
マルチステートメント トランザクションと同様に、インデックスについての説明もあまりありません。このような機能が BigQuery にあることを発見し、その制約事項を理解した瞬間に、ご自身の特定のシナリオで活用する方法がすぐにわかるでしょう。
まとめ
BigQuery のお気に入りの機能で、まだ注目されていないと思うものがありましたら、ぜひお知らせください。Twitter: @ArtemNikulchen1
- チーフ ソフトウェア アーキテクトおよびチャンピオン イノベーター Artem Nikulchenko 氏