最も古いアクティブなクエリ(長時間実行中のクエリとも呼ばれる)は、データベース内でアクティブなクエリのリストであり、クエリの実行時間順に並べられています。これらのクエリを分析して、システムのレイテンシと CPU 使用率が高い場合の原因を特定できます。
Spanner には、実行中クエリ(DML ステートメントを含むクエリなど)を開始時間別に昇順で一覧表示する組み込みテーブル SPANNER_SYS.OLDEST_ACTIVE_QUERIES
が用意されています。このテーブルに変更ストリーム クエリは含まれません。
現在大量のクエリが実行中の場合、システムがこのデータの収集に関して適用するメモリの制約により、結果は合計クエリのサブセットに限定される可能性があります。そのため、Spanner には SPANNER_SYS.ACTIVE_QUERIES_SUMMARY
という追加のテーブルがあり、すべてのアクティブなクエリ(変更ストリーム クエリは除く)の統計情報の概要が表示されます。SQL ステートメントを使用すると、これらの組み込みテーブルの両方から情報を取得できます。
このドキュメントでは、両方のテーブルについて説明し、これらのテーブルを使用するクエリの例を紹介します。最後に、アクティブなクエリによって発生する問題を軽減するのに役立つテーブルの使用方法を示します。
可用性
SPANNER_SYS
データは SQL インターフェースを介してのみ使用できます。例えば:
Google Cloud コンソールのデータベースの Spanner Studio ページ
executeQuery
API
Spanner が提供する他の単一読み取りメソッドは、SPANNER_SYS
をサポートしていません。
OLDEST_ACTIVE_QUERIES
SPANNER_SYS.OLDEST_ACTIVE_QUERIES
は、開始時間で並べ替えられたアクティブなクエリのリストを返します。現在大量のクエリが実行中の場合、Spanner がこのデータの収集に関して適用するメモリの制約により、結果は合計クエリのサブセットに限定される可能性があります。アクティブなすべてのクエリの統計情報の概要を表示するには、ACTIVE_QUERIES_SUMMARY
をご覧ください。
テーブル スキーマ
列名 | タイプ | 説明 |
---|---|---|
START_TIME |
TIMESTAMP |
クエリの開始時間。 |
TEXT_FINGERPRINT |
INT64 |
フィンガープリントは、トランザクションに含まれるオペレーションのハッシュです。 |
TEXT |
STRING |
クエリ ステートメントのテキスト。 |
TEXT_TRUNCATED |
BOOL |
TEXT フィールドのクエリテキストが切り捨てられた場合は true、それ以外の場合は false です。 |
SESSION_ID |
STRING |
クエリを実行しているセッションの ID。これはオブザーバビリティに使用されます。 |
QUERY_ID 。 |
STRING |
クエリの ID。この ID を CALL cancel_query(query_id) とともに使用して、クエリをキャンセルします。 |
クエリの例
次の SQL ステートメントの例は、クライアント ライブラリ、Google Cloud CLI、または Google Cloud コンソールを使用して実行できます。
最も古い実行中クエリを一覧表示する
次のクエリは、クエリの開始時間で並べ替えて、最も古い実行中クエリのリストを返します。
SELECT start_time,
text_fingerprint,
text,
text_truncated,
session_id
FROM spanner_sys.oldest_active_queries
ORDER BY start_time ASC;
start_time | text_fingerprint | テキスト | text_truncated | session_id |
---|---|---|---|---|
2020-07-18T07:52:28.225877Z | -3426560921851907385 | SELECT a.SingerId, a.AlbumId, a.TrackId, b.SingerId as b_id, b.AlbumId as b_albumid, b.TrackId as b_trackId FROM Songs as a CROSS JOIN Songs as b; | False | ACjbPvYsucrtcffHrRK6aObeIjZf12tSUwOsim-g1WC3IhqF4epzICCQR3GCHw |
2020-07-18T07:54:08.622081Z | -9206690983832919848 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE STARTS_WITH(s.FirstName, 'FirstName') LIMIT 1000000; | False | ACjbPvaF3yKiNfxXFod2LPoFaXjKR759Bw1o34206vv0t7eOrD3wxZhu8U6ohQ |
2020-07-18T07:54:08.631744Z | -105437553161169030 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE a.SingerId > 7 LIMIT 1000000; | False | ACjbPvanq3MesDNT98t64KdKAz3TlDZoCC-zgW-FJn91cJHuczQ_cOFN_Hdflw |
2020-07-18T07:54:08.720011Z | -9206690983832919848 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE STARTS_WITH(s.FirstName, 'FirstName') LIMIT 1000000; | False | ACjbPvYIE2QHkhnmMXuAGpB4inK7yMnQjmYgQ9FoygKNaB5KCXu7Sf7f9aghYw |
2020-07-18T07:54:08.731006Z | 6561582859583559006 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE a.SingerId > 10 LIMIT 1000000; | False | ACjbPvYNZ06N2YyvwV0YMlSRBNDtXBqZEK-iAAyPFnFcTmshPvzWkhr034ud7w |
上位 2 つの最も古い実行中クエリの一覧表示
上記のクエリを少しだけ変えると、この例では、クエリの開始時間で並び替えられた上位 2 つの最も古い実行中クエリを返します。
SELECT start_time,
text_fingerprint,
text,
text_truncated,
session_id
FROM spanner_sys.oldest_active_queries
ORDER BY start_time ASC LIMIT 2;
クエリ出力
start_time | text_fingerprint | テキスト | text_truncated | session_id |
---|---|---|---|---|
2020-07-18T07:52:28.225877Z | -3426560921851907385 | SELECT a.SingerId, a.AlbumId, a.TrackId, b.SingerId as b_id, b.AlbumId as b_albumid, b.TrackId as b_trackId FROM Songs as a CROSS JOIN Songs as b; | False | ACjbPvYsucrtcffHrRK6aObeIjZf12tSUwOsim-g1WC3IhqF4epzICCQR3GCHw |
2020-07-18T07:54:08.622081Z | -9206690983832919848 | SELECT a.SingerId, a.AlbumId, a.TrackId, a.SongName, s.FirstName, s.LastName FROM Songs as a JOIN Singers as s ON s.SingerId = a.SingerId WHERE STARTS_WITH(s.FirstName, 'FirstName') LIMIT 1000000; | False | ACjbPvaF3yKiNfxXFod2LPoFaXjKR759Bw1o34206vv0t7eOrD3wxZhu8U6ohQ |
ACTIVE_QUERIES_SUMMARY
その名前が示すように、組み込みテーブル、SPANNER_SYS.ACTIVE_QUERIES_SUMMARY
には、すべてのアクティブなクエリの統計情報の概要を表示されます。次のスキーマに示すように、クエリは経過時間ごとに 3 つのバケットまたはカウンタ(1 秒間以上、10 秒以上、100 秒以上のもの)に分類されます。
テーブル スキーマ
列名 | タイプ | 説明 |
---|---|---|
ACTIVE_COUNT |
INT64 |
実行中のクエリの合計数。 |
OLDEST_START_TIME |
TIMESTAMP |
最も古い実行中クエリの開始時間の上限。 |
COUNT_OLDER_THAN_1S |
INT64 |
1 秒以上経過したクエリの数。 |
COUNT_OLDER_THAN_10S |
INT64 |
10 秒以上経過したクエリの数。 |
COUNT_OLDER_THAN_100S |
INT64 |
100 秒以上経過したクエリの数。 |
1 つのクエリは、これらのバケットの 1 つ以上でカウントされる場合があります。たとえば、クエリが 12 秒間実行されている場合、両方の条件を満たしているため、COUNT_OLDER_THAN_1S
と COUNT_OLDER_THAN_10S
でカウントされます。
クエリの例
次の SQL ステートメントの例は、クライアント ライブラリ、gcloud Spanner、または Google Cloud コンソールを使用して実行できます。
アクティブなクエリの概要を取得する
次のクエリは、実行中のクエリに関する統計情報の概要を返します。
SELECT active_count,
oldest_start_time,
count_older_than_1s,
count_older_than_10s,
count_older_than_100s
FROM spanner_sys.active_queries_summary;
クエリ出力
active_count | oldest_start_time | count_older_than_1s | count_older_than_10s | count_older_than_100s |
---|---|---|---|---|
22 | 2020-07-18T07:52:28.225877Z | 21 | 21 | 1 |
制限事項
ここでの目的は最も包括的な分析を可能にすることにありますが、状況によっては、これらのテーブルに返されるデータにクエリが含まれていない場合があります。
DML クエリ(UPDATE/INSERT/DELETE)は、ミューテーションの適用フェーズ中は含まれません。
一時的なエラーが原因で再起動中の場合、クエリは含まれません。
過負荷のサーバーや応答がないサーバーのクエリは含まれません。
OLDEST_ACTIVE_QUERIES
は読み取り / 書き込みトランザクションでは使用できません。読み取り専用トランザクションでも、トランザクション タイムスタンプを無視して、常に実行時の現在のデータを返します。まれに、部分的な結果でABORTED
エラーが返されることがあります。その場合は、部分的な結果を破棄して、もう一度クエリを実行してください。
アクティブなクエリデータを使用して CPU 使用率が高い場合のトラブルシューティングを行う
クエリ統計とトランザクション統計は、Spanner データベースでのレイテンシのトラブルシューティングに役立つ情報を提供します。これらのツールは、完了したクエリに関する情報を提供します。ただし、システムで実行されているクエリの情報が必要になる場合もあります。たとえば、CPU 使用率が非常に高く、次の質問に答えたい場合を考えてみます
- 現在、実行中のクエリの数は?
- それらはどのようなクエリですか?
- 長時間(100 秒以上)実行されているクエリの数はいくつですか?
- クエリを実行しているセッションはどれですか?
上記の質問の答えに応じて、次の操作を行うことができます。
- 即時解決のためにクエリを実行しているセッションを削除する。
- インデックスを追加してクエリのパフォーマンスを向上させる。
- クエリが定期的なバックグラウンド タスクに関連付けられている場合は、そのクエリの頻度を減らす。
- クエリを実行する権限を持たないユーザーまたはコンポーネントが発行しているクエリを特定する。
このチュートリアルでは、アクティブなクエリを調べ、行うべき操作(もしあれば)を決定します。
アクティブなクエリの概要を取得する
このシナリオの例では、通常の CPU 使用率を上回っているため、次のクエリを実行してアクティブなクエリの概要を返します。
SELECT active_count,
oldest_start_time,
count_older_than_1s,
count_older_than_10s,
count_older_than_100s
FROM spanner_sys.active_queries_summary;
クエリは次の結果を生成します。
active_count | oldest_start_time | count_older_than_1s | count_older_than_10s | count_older_than_100s |
---|---|---|---|---|
22 |
2020-07-18T07:52:28.225877Z |
21 |
21 |
1 |
100 秒を超える時間実行されているクエリが 1 つあることが判明しました。これはデータベースには珍しいため、さらに詳しく調査する必要があります。
アクティブなクエリのリストを取得する
前のステップで、100 秒以上実行されているクエリがあることが判別されました。さらに詳しく調査するため、次のクエリを実行して、上位 5 件の最も古い実行中クエリに関する詳細情報を返します。
SELECT start_time,
text_fingerprint,
text,
text_truncated,
session_id,
query_id
FROM spanner_sys.oldest_active_queries
ORDER BY start_time ASC LIMIT 5;
この例では、2024 年 3 月 28 日のおよそ午後 4 時 44 分 9 秒(EDT)にクエリを実行し、次の結果が返されました(出力全体を確認するには、横方向のスクロールが必要な場合もあります)。
start_time | text_fingerprint | テキスト | text_truncated | session_id | query_id |
---|---|---|---|---|---|
2024-03-28 16:44:09.356939+00:00 | -2833175298673875968 | select * from spanner_sys.oldest_active_queries | false | ACjbPvYsucrtcffHrRK6aObeIjZf12tSUwOsim-g1WC3IhqF4epzICCQR3GCHw | 37190103859320827 |
2020-07-18T07:52:28.225877Z | -3426560921851907385 | SELECT a.SingerId, a.AlbumId, a.TrackId, b.SingerId as b_id, b.AlbumId as b_albumid, b.TrackId as b_trackId FROM Songs as a CROSS JOIN Songs as b; | false | ACjbPvaF3yKiNfxXFod2LPoFaXjKR759Bw1o34206vv0t7eOrD3wxZhu8U6ohQ | 48946620525959556 |
最も古いクエリ(フィンガープリントが -2833175298673875968
)がテーブル内でハイライト表示されます。これはコストが高い CROSS JOIN
ので、対処します。
コストの高いクエリをキャンセルする
この例では、コストの高い CROSS JOIN
を実行しているクエリが見つかったため、このクエリをキャンセルします。前のステップで取得したクエリ結果には query_id
が含まれています。GoogleSQL の場合は次の CALL cancel_query(query_id)
コマンドを、PostgreSQL の場合は spanner.cancel_query(query_id)
コマンドを実行して、クエリをキャンセルできます。
GoogleSQL
CALL cancel_query(query_id)
PostgreSQL
CALL spanner.cancel_query(query_id)
たとえば、次の CALL
ステートメントは、ID 37190103859320827
のクエリをキャンセルします。
CALL cancel_query('37190103859320827')
クエリがキャンセルされたことを確認するには、spanner_sys.oldest_active_queries
テーブルに対してクエリを実行する必要があります。
このチュートリアルでは、SPANNER_SYS.OLDEST_ACTIVE_QUERIES
と SPANNER_SYS.ACTIVE_QUERIES_SUMMARY
を使用して、実行中のクエリを分析し、CPU 使用率の上昇の原因となるクエリに対して必要に応じて対処する方法を示します。もちろん、コストのかかるオペレーションを回避し、ユースケースに適したスキーマを設計すると、より低コストになります。効率的に実行される SQL ステートメントの作成方法については、SQL のベスト プラクティスをご覧ください。
次のステップ
- 別のイントロスペクション ツールについて学習します。
- Spanner が各データベースについて、データベースの情報スキーマ テーブルに保存するその他の情報について学習します。
- Spanner に関する SQL のベスト プラクティスについて学習します。