クエリプロファイルを使用したクエリの分析

Classic Console を介して利用可能なクエリプロファイルは、クエリの実行の詳細を提供します。選択されたクエリについて、クエリの処理計画の主要コンポーネントのグラフィカルな表現、各コンポーネントの統計、およびクエリ全体の詳細と統計が提供されます。

このトピックの内容:

概要

クエリプロファイルを使用する場合

クエリプロファイルは、クエリのメカニズムを理解するための強力なツールです。特定のクエリのパフォーマンスや動作について詳しく知りたい場合や必要な場合に使用できます。 SQL クエリ式の典型的な間違いを見つけて、潜在的なパフォーマンスのボトルネックと改善の機会を特定できるように設計されています。

個々のクエリに関する追加の高レベルの情報は、 Worksheets Worksheet tab ページと History History tab ページのさまざまな列で表示できます。

クエリプロファイルにアクセスする方法

クエリプロファイルには、クエリの詳細ページからアクセスします。そのため、 Query ID 列が表示され、クエリ IDs をクリックできる任意のページからクエリプロファイルにアクセスできます。具体的には:

  • Worksheets Worksheet tab

  • History History tab

注釈

これらのページに Query ID 列が表示されない場合は、ページにある列ヘッダーの1つの横にあるドロップダウンをクリックし、 Columns のリストで Query ID を選択します。

クエリのプロファイルにアクセスするには、

  1. History History tab または Worksheets Worksheet tab ページで、クエリ IDをクリックします。

  2. クエリの詳細ページが表示されます:

    ../_images/ui-profile-detail.png
  3. Profile タブをクリックします。

  4. クエリにプロファイルがある場合は、表示されます(下のスクリーンショットを参照)。

クエリプロファイルインターフェイス

このトピックの目的のために、2つのテーブルを結合する基本的なサンプル SQL クエリを使用しています:

select sum(j)
from x join y using (i)
where j > 300
and i < (select avg(j) from x);
Copy

次のスクリーンショットは、このクエリのプロファイルを示しています:

../_images/ui-profile-step1.png

インターフェイスは、次の主要な要素で構成されています:

ステップ

クエリが複数のステップで処理された場合、各ステップを切り替えることができます。

演算子ツリー

中央のペインには、各演算子ノード間の関係を含む、選択したステップのすべての演算子ノードのグラフィック表示が表示されます。

ノードリスト

中央のペインには、実行時間ごとの折りたたみ可能なオペレーターノードのリストが含まれています。

概要

右側のペインには、クエリプロファイルの概要が表示されます。演算子ノードが選択されると、表示は演算子の詳細に変わります。

ステップ

多くの場合、クエリは複数のステップで処理されます。たとえば、サンプルクエリは2ステップで処理されました。

  • ステップ1は列 x.j の平均を計算しました。

  • ステップ2はこの中間結果を使用して、最終的なクエリ結果を計算しました。

クエリプロファイルでは、各処理ステップが個別のパネルに表示されます。それぞれのステップをクリックして、パネルを切り替えることができます。サンプルクエリでは、 Step 2 をクリックするとビューが次のように変更されます。

../_images/ui-profile-step2.png

演算子ツリー

このツリーは、クエリを構成する演算子ノードと各演算子を接続するリンクのグラフィカルな表現を提供します:

  • 演算子は、クエリの機能的な構成要素です。データアクセス、変換、更新など、データ管理と処理のさまざまな側面を担当します。ツリーの各演算子ノードには、いくつかの基本的な属性が含まれています。

    <型> [#]

    演算子型と ID 番号。ID はクエリプロファイル内の演算子を一意に識別するために使用できます(例えば、上のスクリーンショットの Aggregate [5] および Join [11] など)。

    すべてのタイプの説明については、以下の 演算子タイプ をご覧ください。

    割合

    クエリステップ内でこの演算子が消費した時間の割合(例えば、 Aggregate [5]25%)。この情報は、演算子ノードの下部にあるオレンジ色のバーにも反映され、パフォーマンスが重要な演算子を簡単に視覚的に識別できます。

    ラベル

    オペレーター固有の追加情報(例えば、 Aggregate [5]SUM(X.J))。

  • リンクは、各演算子ノード間を流れるデータを表します。各リンクは、処理された記録の数を提供します(例: Join [11] から Aggregate [5] までの 41.95M)。

注釈

タッチスクリーンを使用していて演算子ツリーが表示されない場合は、タッチスクリーンのタッチイベントインターフェイスが干渉している可能性があります。インターフェイスを一時的に無効にする手順については、Snowflakeコミュニティフォーラムのディスカッションをご参照ください。 クエリプロファイルウィンドウには概要が表示されるが、クエリツリーは表示されない。

実行時間別の演算子ノード

演算子ツリーペインの折りたたみ可能なパネルには、実行時間の降順でノードが一覧表示され、ユーザーは実行時間の観点から最もコストの高い演算子ノードをすばやく見つけることができます。パネルには、クエリの合計実行時間(またはクエリが複数の処理ステップで実行された場合は、表示されたクエリステップの実行時間)の1%以上持続したすべてのノードが一覧表示されます。

リスト内のノードをクリックすると、選択したノードの演算子ツリーが中央に配置されます。

次のスクリーンショットは、 Aggregate [5] 演算子をクリックした後のパネルを示しています:

../_images/ui-profile-nodes-by-execution-time.png

プロファイルの概要/演算子の詳細

右側の概要/詳細ペインには、左側のツリーで選択したコンポーネント(演算子およびリンク)に関する情報が表示されます。表示される情報は、演算子ツリー内のノードが選択されているかどうかによって異なります:

  • 最初は、ツリー内のノードは選択されていないため、パネルには現在のステップの概要情報が表示されます。

  • ノードをクリックしてコンポーネントを選択すると、パネルにコンポーネントの情報が表示されます。

注釈

ノードをクリックした後、ステップレベルの概要情報に戻るには、演算子ツリーの周囲の空のスペースをクリックしてノードの選択を解除するだけです。

概要/詳細ペインは3セクションに分かれています:

実行時間

どの処理タスクがクエリ時間を消費したかについての情報を提供します(以下の クエリ/演算子の詳細 で説明)。さらに、ステップレベルの情報については、指定されたステップの状態とその実行時間を示します。

統計

さまざまな統計に関する詳細情報を提供します(以下の クエリ/演算子の詳細 で説明)。

属性

コンポーネント固有の情報を提供します(以下の 演算子のタイプ で説明)。

次のスクリーンショットは、 Join [11] 演算子をクリックした後の詳細を示しています:

../_images/ui-profile-operator.png

演算子のタイプ

次のセクションでは、最も一般的な演算子タイプとその属性のリストを提供します。

データアクセスおよび生成演算子

TableScan

単一のテーブルへのアクセスを表します。属性:

  • Full table name ---データベースとスキーマを含む、アクセスされたテーブルの名前。

  • Columns ---スキャンされた列のリスト

  • Table alias ---存在する場合は、テーブルエイリアスを使用

  • Extracted Variant paths --- VARIANT 列から抽出されたパスのリスト

ValuesClause

VALUES 句で提供される値のリスト。属性:

  • Number of values ---生成された値の数。

  • Values ---生成された値のリスト。

ジェネレーター

TABLE(GENERATOR(...)) 構造を使用してレコードを生成します。属性:

  • rowCount ---指定されたrowCountパラメーター。

  • timeLimit ---指定されたtimeLimitパラメーター。

ExternalScan

ステージオブジェクトに格納されているデータへのアクセスを表します。ステージから直接データをスキャンするクエリの一部になりますが、データロード COPY クエリにも使用できます。属性:

  • Stage name ---データが読み取られるステージの名前。

  • Stage type ---ステージのタイプ(例: TABLE STAGE)。

InternalObject

内部データオブジェクト(例えば、情報スキーマテーブルや以前のクエリの結果など)へのアクセスを表します。属性:

  • Object Name ---アクセスしたオブジェクトの名前またはタイプ。

データ処理演算子

フィルター

レコードをフィルタリングする操作を表します。属性:

  • Filter condition -フィルターの実行に使用される条件。

参加する

特定の条件で2つの入力を結合します。属性:

  • Join Type ---結合のタイプ(例: INNER、 LEFT OUTER など)

  • Equality Join Condition ---等価ベースの条件を使用する結合の場合、要素の結合に使用される式がリストされます。

  • Additional Join Condition ---一部の結合では、不平等ベースの述語を含む条件が使用されます。それらはここにリストされています。

注釈

等しくない結合述部は、処理速度を大幅に低下させる可能性があるため、可能であれば回避する必要があります。

集計

入力をグループ化し、集計関数を計算します。 GROUP BYや SELECT DISTINCTなどの SQL 構造を表すことができます。属性:

  • Grouping Keys --- GROUP BY が使用される場合、これはグループ化する式をリストします。

  • Aggregate Functions ---各集計グループに対して計算された関数のリスト(例: SUM)。

GroupingSets

GROUPING SETS、 ROLLUP 、 CUBEなどの構造を表します。属性:

  • Grouping Key Sets ---グループ化セットのリスト

  • Aggregate Functions ---各グループに対して計算された関数のリスト(例: SUM)。

WindowFunction

ウィンドウ関数を計算します。属性:

  • Aggregate Functions ---計算されたウィンドウ関数のリスト。

ソート

特定の式の入力を順序付けます。属性:

  • Sort keys ---ソート順を定義する式。

SortWithLimit

ソート後に入力シーケンスの一部、通常は SQL の ORDER BY ... LIMIT ... OFFSET ... 構築の結果を生成します。属性:

  • Sort keys ---ソート順を定義する式。

  • Number of rows ---生成された行数。

  • Offset ---生成されたタプルが発行される順序付けられたシーケンス内の位置。

フラット化

VARIANT レコードを処理し、場合によっては指定されたパスでそれらをフラット化します。属性:

  • input ---データをフラット化するために使用される入力式。

JoinFilter

クエリプランでさらに結合の条件に一致しない可能性があると識別できるタプルを削除する特別なフィルタリング操作。属性:

  • Original join ID ---除外できるタプルを識別するために使用される結合。

UnionAll

2つの入力を連結します。属性:なし。

ExternalFunction

外部関数による処理を表します。

DML 演算子

挿入

INSERT または COPY 操作のいずれかにより、テーブルにレコードを追加します。属性:

  • Input expressions ---挿入される式。

  • Full table name --- 記録が追加される単一のターゲットテーブルの名前。

  • Full table names --- 記録が追加される複数のターゲットテーブルの名前。

削除

テーブルからレコードを削除します。属性:

  • Full table name --- 記録が削除されるテーブルの名前。

更新

テーブル内のレコードを更新します。属性:

  • Full table name ---更新されたテーブルの名前。

マージ

テーブルで MERGE 操作を実行します。属性:

  • Full table name ---更新されたテーブルの名前。

アンロード

ステージ内のテーブルからファイルにデータをエクスポートする COPY 操作を表します。属性:

  • Location - データが保存されるステージの名前。

メタデータ演算子

一部のクエリには、データ処理操作ではなく、純粋なメタデータ/カタログ操作であるステップが含まれます。これらのステップは、単一の演算子で構成されています。例は次のとおりです:

DDL およびトランザクションコマンド

オブジェクト、セッション、トランザクションなどの作成または変更に使用されます。通常、これらのクエリは仮想ウェアハウスによって処理されず、一致する SQL ステートメントに対応するシングルステッププロファイルになります。例:

CREATE DATABASE | SCHEMA | ...

ALTER DATABASE | SCHEMA | TABLE | SESSION | ...

DROP DATABASE | SCHEMA | TABLE | ...

COMMIT

テーブル作成コマンド

テーブルを作成するためのDDL コマンド。例:

CREATE TABLE

他の DDL コマンドと同様に、これらのクエリはシングルステッププロファイルになります。ただし、 CTAS ステートメントで使用する場合など、マルチステッププロファイルの一部にすることもできます。例:

CREATE TABLE ... AS SELECT ...

クエリ結果の再利用

前のクエリの結果を再利用するクエリ。

メタデータベースの結果

データにアクセスすることなく、メタデータのみに基づいて結果が計算されるクエリ。これらのクエリは、仮想ウェアハウスでは処理されません。例:

SELECT COUNT(*) FROM ...

SELECT CURRENT_DATABASE()

その他の演算子

結果

クエリ結果を返します。属性:

  • List of expressions - 生成された式。

クエリ/演算子の詳細

クエリパフォーマンスの分析に役立つように、詳細パネルには2つのクラスのプロファイリング情報があります:

  • カテゴリに分類された実行時間

  • 詳細な統計

さらに、各演算子に対して属性が提供されます(このトピックの 演算子の種類 で説明)。

実行時間

実行時間は、クエリの処理中に「時間が費やされた場所」に関する情報を提供します。費やした時間は、次の順序で表示される次のカテゴリに分類できます:

  • Processing --- CPUによるデータ処理に費やされた時間。

  • Local Disk IO ---ローカルディスクアクセスによって処理がブロックされた時間。

  • Remote Disk IO ---処理がリモートディスクアクセスによってブロックされた時間。

  • Network Communication ---処理がネットワークデータ転送を待機していた時間。

  • Synchronization ---参加しているプロセス間のさまざまな同期アクティビティ。

  • Initialization --- クエリ処理の設定にかかった時間。

統計

詳細ペインで提供される主な情報源は、次のセクションにグループ化されたさまざまな統計です。

  • IO --- クエリ中に実行される入出力操作に関する情報。

    • Scan progress ---これまでに特定のテーブルについてスキャンされたデータの割合。

    • Bytes scanned ---これまでにスキャンされたバイト数。

    • Percentage scanned from cache ---ローカルディスクキャッシュからスキャンされたデータの割合。

    • Bytes written ---書き込まれたバイト数(例: テーブルへのロード時)。

    • Bytes written to result --- 結果オブジェクトに書き込まれたバイト数。たとえば、 select * from . . . は、選択範囲の各フィールドを表す表形式の結果のセットを生成します。一般に、結果オブジェクトは、なんであれクエリの結果として生成されるものを表し、 結果に書き込まれたバイト数 は、返される結果のサイズを表します。

    • Bytes read from result --- 結果オブジェクトから読み取ったバイト数。

    • External bytes scanned ---ステージなどの外部オブジェクトから読み取ったバイト数。

  • DML ---データ操作言語(DML)クエリの統計:

    • Number of rows inserted ---1つまたは複数のテーブルに挿入された行の数。

    • Number of rows updated ---テーブルで更新された行の数。

    • Number of rows deleted ---テーブルから削除された行の数。

    • Number of rows unloaded ---データのエクスポート中にアンロードされた行の数。

  • Pruning ---テーブルのプルーニングの影響に関する情報:

    • Partitions scanned ---これまでにスキャンされたパーティションの数。

    • Partitions total ---特定のテーブル内のパーティションの総数。

  • Spilling ---中間結果がメモリに収まらない操作のディスク使用量に関する情報:

    • Bytes spilled to local storage ---ローカルディスクに流出したデータの量。

    • Bytes spilled to remote storage ---リモートディスクに流出したデータの量。

  • Network ---ネットワーク通信:

    • Bytes sent over the network --- ネットワーク経由で送信されたデータの量。

  • External Functions --- 外部関数の呼び出しに関する情報。

    次の統計は、 SQL ステートメントによって呼び出される各外部関数について表示されます。同じ SQL ステートメントから同じ関数が複数回呼び出された場合は、統計が集計されます。

    • Total invocations --- 外部関数が呼び出された回数。(行が分割されるバッチの数、再試行の数(一時的なネットワークの問題がある場合)などにより、 SQL ステートメントのテキスト内にある外部関数呼び出しの数とは異なる場合がある。)

    • Rows sent --- 外部関数に送信された行数。

    • Rows received --- 外部関数から受信した行数。

    • Bytes sent (x-region) --- 外部関数に送信されたバイト数。ラベルに「(x地域)」が含まれている場合、データは複数の地域に送信されています(請求に影響する可能性あり)。

    • Bytes received (x-region) --- 外部関数から受信したバイト数。ラベルに「(x地域)」が含まれている場合、データは複数の地域に送信されています(請求に影響する可能性あり)。

    • Retries due to transient errors --- 一時的なエラーによる再試行の数。

    • Average latency per call --- Snowflakeがデータを送信してから返されたデータを受信するまでの呼び出し(コール)あたりの平均時間。

    • HTTP 4xx errors --- 4xxステータスコードを返した HTTP リクエストの合計数。

    • HTTP 5xx errors --- 5xxステータスコードを返した HTTP リクエストの合計数。

    • Latency per successful call (avg) --- 成功した HTTP リクエストの遅延平均。

    • Avg throttle latency overhead --- スロットリングが原因の速度低下による、成功したリクエストごとの平均オーバーヘッド(HTTP 429)。

    • Batches retried due to throttling --- HTTP 429エラーが原因で再試行されたバッチの数。

    • Latency per successful call (P50) --- 成功した HTTP リクエストの遅延の50パーセンタイル値。成功したすべてのリクエストの50%で、完了までにかかった時間がこの時間未満。

    • Latency per successful call (P90) --- 成功した HTTP リクエストの遅延の90パーセンタイル値。成功したすべてのリクエストの90%で、完了までにかかった時間がこの時間未満。

    • Latency per successful call (P95) --- 成功した HTTP リクエストの遅延の95パーセンタイル値。成功したすべてのリクエストの95%で、完了までにかかった時間がこの時間未満。

    • Latency per successful call (P99) --- 成功した HTTP リクエストの遅延の99パーセンタイル値。成功したすべてのリクエストの99%で、完了までにかかった時間がこの時間未満。

  • Extension Functions --- 拡張関数の呼び出しに関する情報。

    • Java UDF handler load time --- Java UDF ハンドラーのロードにかかった時間。

    • Total Java UDF handler invocations --- Java UDF ハンドラーが呼び出された回数。

    • Max Java UDF handler execution time --- Java UDF ハンドラーの実行にかかった最大時間。

    • Avg Java UDF handler execution time --- Java UDF ハンドラーの実行にかかった平均時間。

    • Java UDTF process() invocations --- Java UDTF プロセスメソッド が呼び出された回数。

    • Java UDTF process() execution time --- Java UDTF プロセスの実行にかかった時間。

    • Avg Java UDTF process() execution time --- Java UDTF プロセスの実行にかかった平均時間。

    • Java UDTF's constructor invocations --- Java UDTF コンストラクター が呼び出された回数。

    • Java UDTF's constructor execution time --- Java UDTF コンストラクターの実行にかかった時間。

    • Avg Java UDTF's constructor execution time --- Java UDTF コンストラクターの実行にかかった平均時間。

    • Java UDTF endPartition() invocations --- Java UDTF endPartitionメソッド が呼び出された回数。

    • Java UDTF endPartition() execution time --- Java UDTF endPartitionメソッドの実行にかかった時間。

    • Avg Java UDTF endPartition() execution time --- Java UDTF endPartition メソッドの実行にかかった平均時間。

    • Max Java UDF dependency download time --- Java UDF 依存関係のダウンロードにかかった最大時間。

    • Max JVM memory usage --- JVM によって報告されたピークメモリ使用量。

    • Java UDF inline code compile time in ms --- Java UDF インラインコードをコンパイルする時間。

    • Total Python UDF handler invocations --- Python UDF ハンドラーが呼び出された回数。

    • Total Python UDF handler execution time --- Python UDF ハンドラーの実行にかかった合計時間。

    • Avg Python UDF handler execution time --- Python UDFハンドラーの実行にかかった平均時間。

    • Python sandbox max memory usage --- Pythonサンドボックス環境によるピークメモリ使用量。

    • Avg Python env creation time: Download and install packages --- パッケージのダウンロードとインストールを含む、Python環境の作成にかかった平均時間。

    • Conda solver time --- Pythonパッケージの解決でCondaソルバーの実行にかかった時間。

    • Conda env creation time --- Python環境の作成にかかった時間。

    • Python UDF initialization time --- Python UDF の初期化にかかった時間。

    • Number of external file bytes read for UDFs --- UDFs 用に読み取られた外部ファイルのバイト数。

    • Number of external files accessed for UDFs --- UDFs 用にアクセスした外部ファイル数。

    「一時的なエラーによる再試行」などのフィールドの値がゼロの場合、フィールドは表示されません。

クエリプロファイルによって識別される一般的なクエリの問題

このセクションでは、クエリプロファイルを使用して特定およびトラブルシューティングできる問題の一部について説明します。

「爆発」結合

SQL ユーザーのよくある間違いの1つは、結合条件を提供せずにテーブルを結合する(「デカルト積」になる)、または1つのテーブルの記録が、別のテーブルからの記録と複数一致する条件を提供することです。このようなクエリの場合、 Join 演算子は、消費するよりも大幅に(多くの場合、桁違いに)タプルを生成します。

これは、 Join 演算子によって生成されたレコードの数を調べることで確認できます。通常、 Join 演算子が多くの時間を消費することにも反映されます。

次の例は、数百のレコードでの入力を示していますが、数十万のレコードでの出力を示しています:

SELECT tt1.c1, tt1.c2
FROM tt1
JOIN tt2 ON tt1.c1 = tt2.c1
 AND tt1.c2 = tt2.c2;
Copy
../_images/ui-profile-issues-exploding-joins.png

ALLなしのUNION

SQL では、2組のデータを UNION または UNION ALL 構造のいずれかと組み合わせることができます。それらの違いは、 UNION ALL は単純に入力を連結するのに対し、 UNION は同じことを行いますが、重複排除も行います。

よくある間違いは、 UNION ALLのセマンティクスで十分な場合に UNION を使用することです。これらのクエリは、クエリプロファイルに UnionAll 演算子として表示され、余分に Aggregate 演算子が追加されます(重複排除を実行します)。

大きすぎてメモリに収まらないクエリ

一部の操作(例: 巨大なデータセットの重複排除など)では、操作の実行に使用されるコンピューティングリソースで使用可能なメモリ量が、中間結果を保持するのに十分でない場合があります。その結果、クエリ処理エンジンは、ローカルディスクにデータの スピル を開始します。ローカルディスクスペースが十分でない場合、流出したたデータはリモートディスクに保存されます。

この流出は、クエリのパフォーマンスに大きな影響を与える可能性があります(特に、リモートディスクが流出に使用される場合)。これを軽減するには、以下をお勧めします:

  • より大きなウェアハウスを使用する(操作に使用可能なメモリ/ローカルディスクスペースを効果的に増やす)、または

  • 小さいバッチでデータを処理します。

非効率なプルーニング

Snowflakeは、データに関する豊富な統計を収集し、クエリフィルターに基づいてテーブルの不要な部分を読み取らないようにします。ただし、これを有効にするには、データストレージの順序をクエリフィルター属性と関連付ける必要があります。

プルーニングの効率は、 TableScan 演算子の スキャンされたパーティションパーティションの合計 統計を比較することで確認できます。前者が後者のごく一部である場合、プルーニングは効率的です。そうでない場合、プルーニングは効果がありません。

もちろん、プルーニングは、大量のデータを実際にフィルターするクエリにのみ役立ちます。プルーニング統計にデータ削減が示されていないが、 TableScan の上に多数のレコードを除外する Filter 演算子がある場合、これはこのクエリに対して異なるデータ編成が有益であることを示す可能性があります。

プルーニングの詳細については、 Snowflakeテーブル構造について をご参照ください。