AnalyticDB for PostgreSQL は、スロークエリを自動的に記録します。パフォーマンスの問題を診断するには、postgres データベース内の 2 つの組み込みビューをクエリします。qmonitor.instance_slow_queries を使用してインスタンスレベルで分析し、qmonitor.host_slow_queries を使用してノード単位で分析します。
前提条件
開始する前に、以下の点を確認してください。
ご利用のインスタンスが、弾力的ストレージモードで AnalyticDB for PostgreSQL V7.0 を実行しており、マイナーエンジンバージョンが V7.0.5.0 以降である必要があります。マイナーエンジンバージョンの確認または更新については、「マイナーエンジンバージョンの表示」および「マイナーエンジンバージョンの更新」をご参照ください。
スロークエリの診断機能が有効化されている必要があります。「スロークエリの診断機能の有効化または無効化」をご参照ください。
注意事項
スロークエリログは過去 7 日間 のデータを保持し、失敗したクエリは記録されません。
長さが 1,024 バイト を超える SQL ステートメントは、ログ内で切り捨てられます。
実行時間が 1 秒以上かかるすべての SQL ステートメントおよびすべての DDL ステートメントが、デフォルトで記録されます。このしきい値は、Grand Unified Configuration (GUC) パラメーター
slow_query_min_durationで制御されます。システムの安定性を確保するため、このパラメーターのデフォルト設定を変更しないことを推奨します。
スロークエリの診断機能の有効化または無効化
postgres データベースに接続し、以下のコマンドを実行します。
現在のステータスを確認するには:
SHOW adbpg_feature_enable_query_monitor;特定のデータベースに対して機能を有効化するには:
-- <database_name> をご使用のビジネスデータベース名に置き換えます。
ALTER DATABASE <database_name> SET adbpg_feature_enable_query_monitor TO ON;機能を無効化するには、値を OFF に設定します。
スロークエリログのクエリ
以下のすべての例は、qmonitor.instance_slow_queries(インスタンスレベル)または qmonitor.host_slow_queries(ノードレベル)に対して実行されます。実行前に、postgres データベースに接続してください。
両方のビューに含まれるすべてのフィールドの詳細については、「フィールド一覧」をご参照ください。
時間範囲別
過去 30 分間に実行されたすべてのスロークエリをクエリします。
SELECT
query_start AS "開始時刻",
query_end AS "終了時刻",
query_duration_ms AS "実行時間 (ms)",
query_id AS "クエリ ID",
query AS "SQL ステートメント"
FROM qmonitor.instance_slow_queries
WHERE query_start >= now() - interval '30 min';特定の日付(例:2024 年 2 月 26 日)に実行されたすべてのスロークエリをクエリします。
SELECT
query_start AS "開始時刻",
query_end AS "終了時刻",
query_duration_ms AS "実行時間 (ms)",
query_id AS "クエリ ID",
query AS "SQL ステートメント"
FROM qmonitor.instance_slow_queries
WHERE query_start >= '2024-02-26 00:00:00'
AND query_end <= '2024-02-27 00:00:00';リソース消費量別(インスタンスレベル)
query_duration_ms は、以下の 4 つのサブフィールドの合計値です。
| サブフィールド | 測定対象 |
|---|---|
optimizer_duration_ms | 実行計画の生成に要した時間 |
lock_wait_time_ms | ロック待ちに要した時間 |
queue_wait_time_ms | リソースキュー待ちに要した時間 |
executor_duration_ms | 実行エンジン上でのクエリ実行に要した時間 |
クエリが遅い場合、どのサブフィールドの値が支配的かを確認することで、ボトルネックを特定できます。たとえば、queue_wait_time_ms の値が高い場合は、実行そのものではなく、リソースキューの競合が原因である可能性があります。
過去 30 分間の CPU 時間上位 20 件
SELECT
(cpu_time_ms / 1000)::text || ' s' AS "CPU 時間",
query_start AS "開始時刻",
query_end AS "終了時刻",
query_duration_ms AS "実行時間 (ms)",
query_id AS "クエリ ID",
query AS "SQL ステートメント"
FROM qmonitor.instance_slow_queries
WHERE query_start >= now() - interval '30 min'
ORDER BY cpu_time_ms DESC
LIMIT 20;過去 30 分間のメモリ使用量上位 20 件
SELECT
pg_size_pretty(mem_bytes) AS "メモリ使用量",
query_start AS "開始時刻",
query_end AS "終了時刻",
query_duration_ms AS "実行時間 (ms)",
query_id AS "クエリ ID",
query AS "SQL ステートメント"
FROM qmonitor.instance_slow_queries
WHERE query_start >= now() - interval '30 min'
ORDER BY mem_bytes DESC
LIMIT 20;mem_bytes は、ノード間で集計されたピークメモリ使用量を記録します。この値は実際のメモリ使用量を近似したものであり、クエリ実行中のメモリの変動により正確な値ではありません。特定のタイムウィンドウ(例:2024 年 2 月 26 日 00:00~12:00)における CPU 時間上位 10 件
SELECT
(cpu_time_ms / 1000)::text || ' s' AS "CPU 時間",
query_start AS "開始時刻",
query_end AS "終了時刻",
query_duration_ms AS "実行時間 (ms)",
query_id AS "クエリ ID",
query AS "SQL ステートメント"
FROM qmonitor.instance_slow_queries
WHERE query_start >= '2024-02-26 00:00:00'
AND query_end <= '2024-02-26 12:00:00'
ORDER BY cpu_time_ms DESC
LIMIT 10;リソース消費量別(ノードレベル)
特定のノードにおけるスロークエリの診断には、qmonitor.host_slow_queries を使用します。
ノードにおける過去 30 分間の CPU 時間上位 20 件
SELECT
(host_cpu_time_ms / 1000)::text || ' s' AS "CPU 時間",
query_start AS "開始時刻",
query_end AS "終了時刻",
query_duration_ms AS "実行時間 (ms)",
query_id AS "クエリ ID",
query AS "SQL ステートメント"
FROM qmonitor.host_slow_queries
WHERE hostname = '<node_hostname>'
AND query_start >= now() - interval '30 min'
ORDER BY host_cpu_time_ms DESC
LIMIT 20;ノードにおける過去 30 分間のメモリ使用量上位 20 件
SELECT
pg_size_pretty(host_mem_bytes) AS "メモリ使用量",
query_start AS "開始時刻",
query_end AS "終了時刻",
query_duration_ms AS "実行時間 (ms)",
query_id AS "クエリ ID",
query AS "SQL ステートメント"
FROM qmonitor.host_slow_queries
WHERE hostname = '<node_hostname>'
AND query_start >= now() - interval '30 min'
ORDER BY host_mem_bytes DESC
LIMIT 20;<node_hostname> は、診断対象ノードの実際のホスト名に置き換えてください。
ユーザー別
過去 10 分間におけるユーザーごとのスロークエリ数をカウントし、最も多くのスロークエリを生成しているアカウントを特定します。
SELECT
user_name AS "ユーザー",
COUNT(1) AS "スロークエリ数"
FROM qmonitor.instance_slow_queries
WHERE query_start >= now() - interval '10 min'
GROUP BY user_name
ORDER BY COUNT(1) DESC;クエリ ID 別
特定のスロークエリの完全な詳細をクエリ ID で取得します。
SELECT * FROM qmonitor.instance_slow_queries
WHERE query_id = '<query_id>';スロークエリログのエクスポート
SELECT 文を使用して、qmonitor.instance_slow_queries または qmonitor.host_slow_queries のデータを、内部テーブル、Object Storage Service (OSS) バケット、または MaxCompute テーブルにエクスポートします。エクスポートメソッドについては、「データレイク分析」をご参照ください。
AnalyticDB for PostgreSQL では、スロークエリログに対してインデックスが作成されており、また query_start でパーティション分割されています。パフォーマンス向上のため、全表スキャンを回避するために、必ず query_start を WHERE 句に含めてください。
たとえば、2024 年 2 月 26 日 13:00 から 16:00 までのログをエクスポートする場合:
-- SELECT ステートメントにこの条件を追加します。
WHERE query_start >= '2024-02-26 13:00:00'
AND query_start <= '2024-02-26 16:00:00'しきい値の設定
これらの設定項目を変更できるのは、スーパーユーザのみです。
slow_query_min_duration
スロークエリとして記録されるクエリの最小実行時間を制御します。デフォルト値は 1s です。この設定項目を変更することで、1 秒未満のクエリについてもスロークエリを収集できます。
実行時間がこの値以上の場合、SQL ステートメント、実行時間、および関連するメトリックが記録されます。
スロークエリの収集を完全に無効化するには、値を
-1に設定します。
特定のデータベースに対してしきい値を変更するには(スーパーユーザ権限が必要):
-- 5 秒以上かかるスロークエリを収集します。
ALTER DATABASE '<database_name>' SET slow_query_min_duration = '5s';現在のセッションのみに対してしきい値を変更するには(任意のユーザーが実行可能):
SET slow_query_min_duration = '5s';slow_query_plan_min_duration
スロークエリの実行計画を収集するための最小実行時間を制御します。デフォルト値は 10s です。
実行時間がこの値以上の場合、実行計画がクエリメトリックとともに収集されます。
即時的な実行計画の検査には、
EXPLAINを使用してください。自動的な実行計画収集は不要です。実行計画の収集を完全に無効化するには、値を
-1に設定します。
特定のデータベースに対してしきい値を変更するには(スーパーユーザ権限が必要):
ALTER DATABASE '<database_name>' SET slow_query_plan_min_duration = '10s';現在のセッションのみに対してしきい値を変更するには:
SET slow_query_plan_min_duration = '10s';フィールド一覧
qmonitor.instance_slow_queries(インスタンスレベル)
| フィールド | 型 | 説明 |
|---|---|---|
query_id | text | クエリの固有 ID。 |
session_id | integer | クエリセッションの ID。 |
db_name | character varying(128) | クエリ対象のデータベース名。 |
user_name | character varying(128) | クエリを実行したユーザー名。 |
application_name | character varying(128) | クエリを実行したアプリケーション名。 |
client_hostname | character varying(128) | クライアントのホスト名。 |
client_addr | character varying(128) | クライアントの IP アドレス。 |
client_port | character varying(32) | クライアントのポート番号。 |
rsg_name | character varying(128) | クエリがアクセスしたテーブルに関連付けられたリソースグループ名。 |
query_start | timestamptz | クエリの開始時刻。 |
query_end | timestamptz | クエリの終了時刻。 |
query_duration_ms | bigint | クエリの総実行時間(ミリ秒)。optimizer_duration_ms + lock_wait_time_ms + queue_wait_time_ms + executor_duration_ms の合計値と等しくなります。 |
optimizer_duration_ms | bigint | 実行計画の生成に要した時間(ミリ秒)。複雑な SQL ステートメントほど時間がかかります。 |
lock_wait_time_ms | bigint | ロック待ち時間(ミリ秒)。 |
queue_wait_time_ms | bigint | リソースキュー待ち時間(ミリ秒)。 |
executor_duration_ms | bigint | 実行エンジン上でのクエリ実行に要した時間(ミリ秒)。 |
query | text | SQL ステートメントのテキスト。 |
is_plpgsql | boolean | クエリが PL/pgSQL ストアドプロシージャであるかどうか。 |
query_optimizer | character varying(16) | 使用されたオプティマイザー。有効な値:ORCA、Planner。 |
access_tables | text | クエリがアクセスしたテーブル名。 |
result_rows | bigint | 返された行数。INSERT ステートメントの場合は、挿入された行数。 |
num_segments | integer | クエリが実行されたコンピュートノード数。 |
num_slices | integer | クエリ実行計画内のスライス数。 |
cpu_time_ms | numeric | コーディネーターノードおよびすべてのコンピュートノードを含む総 CPU 時間(ミリ秒)。 |
mem_bytes | numeric | ノードごとの累積ピークメモリ使用量。実際のメモリ使用量を近似したものであり、正確な値ではありません。 |
spill_bytes | numeric | クエリが実行されたコンピュートノード上でディスクに保存されたファイルの最大数の累積値。この値はクエリによるディスク領域の消費量を概算したものであり、正確な値ではありません。 |
qmonitor.host_slow_queries(ノードレベル)
| フィールド | 型 | 説明 |
|---|---|---|
hostname | character varying(128) | ノードのホスト名。 |
hostrole | text | ノードのロール。有効な値:master(コーディネーターノード)、segment(コンピュートノード)。 |
query_id | text | クエリの固有 ID。 |
db_name | character varying(128) | クエリ対象のデータベース名。 |
user_name | character varying(128) | クエリを実行したユーザー名。 |
query_start | timestamptz | クエリの開始時刻。 |
query_end | timestamptz | クエリの終了時刻。 |
query | text | SQL ステートメントのテキスト。 |
query_duration_ms | bigint | クエリの実行時間(ミリ秒)。 |
optimizer_duration_ms | bigint | 実行計画の生成に要した時間(ミリ秒)。 |
host_cpu_time_ms | numeric | このノードにおけるクエリの CPU 時間(ミリ秒)。 |
host_mem_bytes | numeric | このノードにおけるクエリのピークメモリ使用量。 |
host_spill_bytes | numeric | このノード上でディスクにスピルされた累積最大データ量。 |