クエリプラン ビジュアライザを使用したクエリのチューニング

クエリプラン ビジュアライザを使用すると、クエリを評価するために Spanner によって選択されたクエリプランプランの構造をすばやく把握できます。このガイドでは、クエリプランを使用してクエリの実行方法を理解する方法について説明します。

準備

このガイドで説明する Google Cloud コンソールのユーザー インターフェースの各要素について理解を深めるには、次の内容をご覧ください。

Google Cloud コンソールでクエリを実行する

  1. Google Cloud コンソールで Spanner の [インスタンス] ページに移動します。

    インスタンス ページに移動

  2. クエリを実行するデータベースを含むインスタンスの名前を選択します。

    Google Cloud コンソールにインスタンスの [概要] ページが表示されます。

  3. クエリを実行するデータベースの名前を選択します。

    Google Cloud コンソールにデータベースの [概要] ページが表示されます。

  4. サイドメニューで、[Spanner Studio] をクリックします。

    Google Cloud コンソールに、データベースの Spanner Studio ページが表示されます。

  5. エディタペインで SQL クエリを入力します。
  6. [実行] をクリックします。

    Spanner がクエリを実行します。

  7. [説明] タブをクリックして、クエリプランの可視化を表示します。

Query Editor のツアー

[Spanner Studio] ページには、SQL クエリと DML ステートメントを入力または貼り付け、データベースに対して実行し、それらの結果とクエリ実行プランを表示できるクエリタブがあります。次のスクリーンショットでは、[Spanner Studio] ページの主要なコンポーネントに番号が付けられています。

アノテーション付きクエリページ。
図 7. アノテーション付きクエリページ。
  1. タブバーには、開いているクエリタブが表示されます。新しいタブを作成するには、[新しいタブ] をクリックします。

    タブバーにはクエリ テンプレートの一覧も表示され、データベース クエリ、トランザクション、読み取りなどに関する分析情報を提供するクエリを貼り付けるときに使用できます。詳しくは、イントロスペクション ツールの概要を参照ください。

  2. エディタ コマンドバーには、次のオプションがあります。
    • [実行コマンドは、編集ペインに入力されたステートメントを実行し、[結果] タブにクエリ結果を生成し、[説明] タブにクエリ実行プランを生成します。デフォルトの動作は、プルダウンを使用して [結果のみ] または [説明のみ] を生成するように変更します。

      エディタでハイライト表示すると、[実行] コマンドが [選択項目を実行] に変更され、選択した内容だけを実行できるようになります。

    • [Clear query] コマンドは、エディタ内のすべてのテキストを削除し、[結果] と [説明] サブタブをクリアします。
    • FORMAT QUERY コマンドにより、読みやすくするために、Query Editor でステートメントがフォーマットされます。
    • SHORTCUTS コマンドにより、エディタで使用できる一連のキーボード ショートカットが表示されます。
    • [SQL クエリのヘルプ] リンクにより、ブラウザタブが開き、SQL クエリ構文に関するドキュメントが表示されます。

    クエリは、エディタで更新されるたびに自動的に検証されます。ステートメントが有効な場合は、エディタ コマンドバーに確認のチェックマークと「有効」というメッセージが表示されます。問題がある場合は、詳細を示すエラー メッセージが表示されます。

  3. エディタに SQL クエリと DML ステートメントを入力します。 複数行ステートメントの場合、これらは色分けされ、行番号が自動的に追加されます。

    エディタで複数のステートメントを入力する場合は、最後のステートメントを除き、各ステートメントの後に終了セミコロンを使用する必要があります。

  4. クエリタブの下部ペインには、3 つのサブタブがあります。
    • [スキーマ] サブタブには、データベース内のテーブルとそのスキーマが表示されます。エディタでステートメントを作成するときに、クイック リファレンスとして使用します。
    • [結果] サブタブには、エディタでステートメントを実行した結果が表示されます。結果テーブルおよび INSERT や >UPDATE などの DML ステートメントを表示するクエリの場合、影響を受ける行の数を示すメッセージが表示されます。
    • [説明] サブタブには、エディタでステートメントを実行するときに作成されるクエリプランの視覚的なグラフが表示されます。
  5. [結果] と [説明] のサブタブのどちらにも、表示するステートメントの結果やクエリプランを選択するために使用するステートメント セレクタが用意されています。

サンプリングされたクエリプランを表示する

    場合によっては、サンプリングされたクエリプランを表示して、クエリのパフォーマンスの推移を時間推移とともに比較することもできます。CPU の消費量が多いクエリの場合、Spanner ではサンプリングされたクエリプランは Google Cloud コンソールの [Query Insights] ページに 30 日間保持されます。サンプリングされたクエリプランを表示するには:

  1. Google Cloud コンソールで Spanner の [インスタンス] ページに移動します。

    インスタンス ページに移動

  2. 調査するクエリを含むインスタンスの名前をクリックします。

    Google Cloud コンソールにインスタンスの [概要] ページが表示されます。

  3. [ナビゲーション] メニューの [オブザーバビリティ] という見出しの配下にある、[Query Insights] をクリックします。

    Google Cloud コンソールにインスタンスの [Query Insights] ページが表示されます。

  4. [データベース プルダウン] メニューで、調査するクエリを含むデータベースを選択します。

    Google Cloud コンソールに、データベースのクエリ分析情報ページが表示されます。TopN クエリとタグのテーブルには、CPU 使用率で並べ替えられた上位のクエリとリクエストタグのリストが表示されます。

  5. サンプリングされたクエリプランを表示する CPU 使用率の高いクエリを探します。そのクエリの [FPRINT] 値をクリックします。

    [クエリの詳細] ページには、時間の経過に伴うクエリのクエリプランのサンプルグラフが表示されます。現在の時刻の最大 7 日前までズームアウトできます。 注: クエリプランは、PartitionQuery API およびパーティション化 DML クエリから取得したパーティション トークンを使用するクエリではサポートされません。

  6. グラフ内のドットのいずれかをクリックすると、古いクエリプランが表示され、クエリの実行中に実行されたステップが可視化されます。任意の演算子をクリックして、演算子に関する展開された情報を表示することもできます。

    クエリプランのグラフの例。
    図 8. クエリプランのグラフの例。

クエリプラン ビジュアライザのツアーを見る

次のスクリーンショットでは、ビジュアライザの主要なコンポーネントにアノテーションが付けられ、さらに説明されています。クエリタブでクエリを実行した後、クエリエディタの下にある [説明] タブを選択してクエリ実行プラン ビジュアライザを開きます。

次の図のデータフローはボトムアップです。つまり、すべてのテーブルとインデックスが図の一番下に表示され、最終出力が一番上になります。

アノテーション付きクエリプラン ビジュアライザ
図 9。 アノテーション付きクエリプラン ビジュアライザ。
  • 実行したクエリによって、プランの可視化が大きくなる可能性があります。詳細の表示と非表示を切り替えるには、[EXPANDED/COMPACT] 表示セレクタを切り替えます。ズーム コントロールを使用すると、表示するプランの量をいつでもカスタマイズできます。
  • Spanner によるクエリの実行方法を表す代数的論理が、非巡回グラフとして描画されます。ここで、各ノードは、入力から行を取り込み、親に行を作り出すイテレータに対応します。プランの例を、図 9 に示します。図をクリックすると、プランの詳細の一部が拡大表示されます。

    ビジュアル プランのスクリーンショットのサムネイル
    図 9.ビジュアル プランのサンプル(クリックして拡大)。
    ビジュアル プランの拡大スクリーンショット

    グラフの各ノード(カード)はイテレータを表し、次の情報が含まれます。

    • イテレータ名。イテレータは、入力から行を消費し、行を生成します。
    • ランタイム統計情報には、返された行数、レイテンシ、CPU の使用量が表示されます。
    • クエリ実行プランで発生する可能性のある問題を特定するために、次の視覚的な手がかりが用意されています。
    • ノード内の赤いバーは、レイテンシと CPU 時間をこのイテレータとクエリ全体とで比較した割合の視覚的なインジケーターです。
    • 各ノードを接続する線の太さは行数を表します。線が太いほど、次のノードに渡される行数が多くなります。コネクタの上にポインタを置くと、実際の行数が各カードに表示されます。
    • テーブル全体のスキャンが実行されたノードに警告を示す三角形が表示されます。情報パネルでの詳細には、インデックスの追加や、可能であればフルスキャンを避けるために他の方法でクエリやスキーマを修正するなどの推奨事項が含まれます。
    • プラン内のカードを選択すると、右側の情報パネル(5)で詳細が表示されます。

  • 実行プランのミニマップには、プラン全体の縮小ビューが表示されます。これは、実行プラン全体の形状を決定したり、プランの各部分にすばやく移動するのに便利です。ミニマップ上で直接ドラッグするか、フォーカスしたい場所をクリックして、ビジュアル プランの他の部分に移動します。
  • [JSON をダウンロード] を選択すると、実行プランの JSON バージョンがダウンロードされます。これはサポートに関して Spanner チームに問い合わせる際に役に立ちます。
  • 情報パネルには、クエリプラン図で選択したノードに関する詳細なコンテキスト情報が表示されます。情報は次のカテゴリに分類されます。
    • [Iterator information] は、グラフで選択したイテレータ カードに関する詳細とランタイム統計情報を提供します。
    • [クエリの概要] には、返された行数とクエリの実行に要した時間に関する詳細情報が表示されます。目立つものは、他の演算子に比べて非常に大きなレイテンシが発生して、CPU をかなり多く消費し、大量のデータ行を返す演算子です。
    • クエリ実行タイムラインは、各マシングループによるクエリの一部の実行時間を示す時間ベースのグラフです。クエリの実行時間全体を通して、マシングループが実行中であるとは限りません。クエリの実行中にマシングループが複数回実行される可能性もありますが、このタイムラインには、最初の実行の開始時刻と最後の回の終了時刻のみが記載されています。
  • パフォーマンスが低いクエリのチューニング

    想定として、自社で、キャスト、制作会社、映画の詳細などの映画に関する情報を含むオンライン映画データベースを運営しているとします。そのサービスは Spanner で実行されますが、最近いくつかのパフォーマンスの問題が生じています。

    サービスのリード デベロッパーとして、サービスの評価が低いためにパフォーマンスの問題を調査するように求められます。Google Cloud コンソールを開き、データベース インスタンスに移動して、Query Editor を開きます。次のクエリをエディタに入力し、実行します。

    SELECT
      t.title,
      MIN(t.production_year) AS year,
      ANY_VALUE(mc.note HAVING MIN t.production_year) AS note
    FROM
      title AS t
    JOIN
      movie_companies AS mc
    ON
      t.id = mc.movie_id
    WHERE
      t.title LIKE '% the %'
    GROUP BY
      title;
    

    このクエリの実行結果は、次のスクリーンショットに表示されます。Query Editor で [FORMAT QUERY] を選択してクエリの形式を整えました。画面の右上にも、クエリが有効であることの通知が表示されます。

    元のクエリが表示された Query Editor
    図 1: 元のクエリが表示された Query Editor。

    Query Editor の下にある [結果] タブに、クエリが 2 分で完了したことが示されています。クエリを詳しく調べることで、クエリが効率的かどうかを確認します。

    クエリプラン ビジュアライザで速度の遅いクエリを分析する

    この時点では、前のステップのクエリには 2 分以上かかるものの、クエリができるだけ効率的で、この時間が予想どおりであるかどうかは不明です。

    Query Editor のすぐ下にある [説明] タブを選択すると、クエリを実行して結果を返すために Spanner によって作成された実行プランが視覚的に表示されます。

    次のスクリーンショットに示すプランは比較的大きなものですが、このズームレベルでも、次のような観察を行えます。

    • 右側の情報パネルのクエリの概要に基づいて、約 300 万行がスキャンされ、最終的に 64K 未満の結果が返されたことがわかりました。

    • [クエリ実行タイムライン] パネルで、4 つのマシングループがクエリに関与していることもわかります。マシングループは、クエリの一部の実行を担当します。演算子は 1 台以上のマシンで実行される場合があります。タイムラインでマシングループを選択すると、そのグループでクエリが実行されたビジュアルプランの部分が視覚的に示されます。

    元のクエリの視覚的な説明を表示するクエリプラン ビジュアライザ
    図 2.元のクエリを視覚化したプランを示すクエリプラン ビジュアライザ。

    これらの要因により、結合をデフォルトで Spanner が選択している適合結合からハッシュ結合に変更することで、パフォーマンスが向上する可能性があると判断されます。

    クエリを改善する

    クエリのパフォーマンスを向上させるには、JOIN のヒントを使用して結合メソッドをハッシュ結合に変更します。この JOIN の実装では、セット単位で処理が実行されます。

    更新されたクエリは次のとおりです。

    SELECT
      t.title,
      MIN(t.production_year) AS year,
      ANY_VALUE(mc.note HAVING MIN t.production_year) AS note
    FROM
      title AS t
    JOIN
      @{join_method=hash_join} movie_companies AS mc
    ON
      t.id = mc.movie_id
    WHERE
      t.title LIKE '% the %'
    GROUP BY
      title;
    

    次のスクリーンショットは、更新されたクエリを示しています。スクリーンショットに示されているように、クエリは 5 秒未満で完了し、この変更の前よりランタイムが 120 秒以上も改善されました。

    改善されたクエリを表示する Query Editor
    図 3.改善されたクエリを表示する Query Editor。

    次の図に示される新しいビジュアル プランをチェックして、この改善の内容を確認します。

    Cloud コンソール UI におけるクエリの可視化
    図 4.クエリの改善後のクエリプランの可視化(クリックして拡大)。

    ビジュアル プランの拡大スクリーンショット

    すぐに次のような違いに気がつきます。

    • このクエリの実行には 1 つのマシングループのみが含まれていた。

    • 集約の数が大幅に減少した。

    まとめ

    このシナリオでは、実行に時間がかかるクエリを実行し、ビジュアル プランを見て、効率が悪い箇所を探しました。クエリとプランの変更前と変更後の概要を次に示します。各タブでは、実行したクエリと、クエリ実行プランの完全な可視化表現を簡潔に示します。

    SELECT
      t.title,
      MIN(t.production_year) AS year,
      ANY_VALUE(mc.note
      HAVING
        MIN t.production_year) AS note
    FROM
      title AS t
    JOIN
      movie_companies AS mc
    ON
      t.id = mc.movie_id
    WHERE
      t.title LIKE '% the %'
    GROUP BY
      title;
    
    改善前のビジュアル プランのコンパクト表示。
    図 5. 改善前のビジュアル プランのコンパクト表示。

    SELECT
      t.title,
      MIN(t.production_year) AS year,
      ANY_VALUE(mc.note
      HAVING
        MIN t.production_year) AS note
    FROM
      title AS t
    JOIN
      @{join_method=hash_join} movie_companies AS mc
    ON
      t.id = mc.movie_id
    WHERE
      t.title LIKE '% the %'
    GROUP BY
      title;
    
    改善後のビジュアル プランのコンパクト表示。
    図 6. 改善後のビジュアル プランのコンパクト表示。

    このシナリオで、改善できる箇所を示したものは、テーブル title の行の大部分がフィルタ LIKE '% the %' に適合したことでした。行数が非常に多い別テーブルでのシークは、高コストになる可能性があります。結合の実装をハッシュ結合に変更したことで、パフォーマンスが大幅に向上しました。

    次のステップ