最も古いアクティブなクエリ(長時間実行中のクエリとも呼ばれる)は、データベース内でアクティブなクエリのリストであり、クエリの実行時間順に並べられています。これらのクエリを分析して、システムのレイテンシと 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 がこのデータの収集に関して適用するメモリの制約により、結果は合計クエリのサブセットに限定される可能性があります。テーブル内のすべての列は null 値を許容できます。アクティブなすべてのクエリの統計情報の概要を表示するには、ACTIVE_QUERIES_SUMMARY
をご覧ください。
テーブル スキーマ
列名 | 型 | 説明 |
---|---|---|
START_TIME |
TIMESTAMP |
クエリの開始時間。 |
TEXT_FINGERPRINT |
INT64 |
フィンガープリントは、トランザクションに含まれるオペレーションのハッシュです。 |
TEXT |
STRING |
クエリ ステートメントのテキスト。 |
TEXT_TRUNCATED |
BOOL |
TEXT フィールドのクエリテキストが切り捨てられた場合は true、それ以外の場合は false です。 |
SESSION_ID |
STRING |
クエリを実行しているセッションの ID。セッション 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; | 偽 | 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; | 偽 | 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; | 偽 | 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; | 偽 | 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; | 偽 | 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; | 偽 | 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; | 偽 | 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
FROM spanner_sys.oldest_active_queries
ORDER BY start_time ASC LIMIT 5;
この例では、2020 年 7 月 18 日(土)のおよそ午前 12 時 54 分 18 秒(太平洋夏時間)にクエリを実行した結果、次の結果が生成されました(出力全体を確認するには、横方向のスクロールが必要な場合もあります)。
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; | 偽 | 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; | 偽 | 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; | 偽 | 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; | 偽 | ACjbPvYNZ06N2YyvwV0YMlSRBNDtXBqZEK-iAAyPFnFcTmshPvzWkhr034ud7w |
最も古いクエリ(フィンガープリントが -3426560921851907385
)がテーブル内でハイライト表示されます。これはコストが高い CROSS JOIN
ので、 対処します。
コストの高いクエリのキャンセル
コストの高い CROSS JOIN
を実行しているクエリが見つかったので、このクエリをキャンセルします。前述の手順のクエリ結果には、session_id
が含まれています。これは、クエリを実行しているセッションの ID です。この場合、次の gcloud spanner databases sessions delete
コマンドを実行して、その ID でセッションを削除することにより、クエリがキャンセルされます。
gcloud spanner databases sessions delete\
ACjbPvYsucrtcffHrRK6aObeIjZf12tSUwOsim-g1WC3IhqF4epzICCQR3GCHw \
--database=singer_db --instance=test-instance
このチュートリアルでは、SPANNER_SYS.OLDEST_ACTIVE_QUERIES
と SPANNER_SYS.ACTIVE_QUERIES_SUMMARY
を使用して、実行中のクエリを分析し、CPU 使用率の上昇の原因となるクエリに対して必要に応じて対処する方法を示します。もちろん、コストのかかるオペレーションを回避し、ユースケースに適したスキーマを設計すると、より低コストになります。効率的に実行される SQL ステートメントの作成方法については、SQL のベスト プラクティスをご覧ください。
次のステップ
- 別のイントロスペクション ツールについて学習します。
- Spanner が各データベースについて、データベースの情報スキーマ テーブルに保存するその他の情報について学習します。
- Spanner に関する SQL のベスト プラクティスについて学習します。