Hologres インスタンスの応答またはクエリの速度が低下した場合、スロークエリのログをクエリおよび分析して問題を特定できます。 スロークエリのログをクエリおよび分析することで、スロークエリと失敗したクエリを識別および分析できます。 その後、最適化対策を講じてシステム パフォーマンスを向上させることができます。 このトピックでは、Hologres でスロークエリのログを表示および分析する方法について説明します。
リリースノート
Hologres バージョン | 説明 | 備考 |
V0.10 | スロークエリのログをクエリおよび分析する機能が追加されました。 |
|
V2.2.7 | log_min_duration_statement パラメータのデフォルト値が最適化されました。 | スロークエリのログには、実行されたすべてのデータ定義言語(DDL)文、実行に失敗したすべての SQL 文、および実行時間が Hologres V2.2.7 以降では、 |
制限
Hologres でスロークエリのログをクエリする場合は、次の項目に注意してください。
デフォルトでは、過去 1 か月のスロークエリのログが保持されます。 過去 1 か月以内の任意の期間のスロークエリのログをクエリできます。
システムの安定性を確保し、トラフィックの過負荷を防ぐため、クエリごとに最大 10,000 件のスロークエリのログがサーバーから返されます。 スロークエリのログの一部のフィールドの長さは制限されています。 詳細については、
hologres.hg_query_log
テーブルのフィールドの説明を参照してください。スロークエリのログは、Hologres のメタデータ ウェアハウス システムに属します。 スロークエリのログのクエリに失敗しても、インスタンスでのクエリに悪影響はありません。 したがって、スロークエリのログの安定性は、Hologres のサービスレベル契約(SLA)では規定されていません。
hologres.hg_query_log テーブルのクエリ
Hologres のスロークエリのログは、hologres.hg_query_log システム テーブルに保存されます。
Hologres V0.10 以降では、Hologres は実行時間が 100 ミリ秒を超えるデータ操作言語(DML)クエリのログと、すべての DDL 文のログを収集します。
Hologres V3.0.2 以降では、Hologres は 100 ミリ秒未満を消費する DML およびデータクエリ言語(DQL)クエリのログも収集および集計します。
Hologres は、SQL フィンガープリントを持ち、100 ミリ秒未満を消費する、正常に実行された DQL および DML クエリのログを収集および集計します。
ほとんどの場合、Hologres は server_addr、usename、datname、warehouse_id、application_name、および digest フィールドの値を集計します。
Hologres は、接続ごとに 1 分ごとにフィールド値を集計して報告します。
次の表に、hologres.hg_query_log システム テーブルに含まれるフィールドを示します。
フィールド | データ型 | 100 ミリ秒以上を消費する DML および DQL クエリの説明 | 100 ミリ秒未満を消費する DML および DQL クエリの説明 |
usename | text | クエリを開始したユーザーの名前。 | クエリを開始したユーザーの名前。 |
status | text | クエリのステータス。 値は、クエリが成功したかどうかを示します。 有効な値:
| クエリのステータス。 SUCCESS に固定されています。 成功したクエリのログのみが集計されます。 |
query_id | text | クエリのユニーク ID。 失敗したクエリにはすべて ID がありますが、成功したクエリには ID がない場合があります。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリの ID。 フィールド値は、プライマリ キーに基づいて集計されます。 |
digest | text | SQL フィンガープリント。 SELECT、INSERT、DELETE、または UPDATE クエリの場合、システムは MD5 ハッシュ値をクエリの SQL フィンガープリントとして計算します。 SQL フィンガープリントを収集および計算する方法の詳細については、このトピックの SQL フィンガープリント を参照してください。 説明 Hologres V2.2 以降では、このテーブルに digest フィールドが追加され、クエリの SQL フィンガープリントが保存されます。 Hologres インスタンスのバージョンが V2.1 以前の場合は、Hologres テクニカル サポートに連絡してインスタンスをアップグレードしてください。 | SQL フィンガープリント。 |
datname | text | データのクエリ元のデータベースの名前。 | データのクエリ元のデータベースの名前。 |
command_tag | text | クエリのタイプ。 有効な値:
| 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリのタイプ。 |
duration | integer | クエリに消費された時間(ミリ秒)。
デフォルトでは、システムはすべての DDL 文と、1 秒以上を消費する DML 文のみを表示します。 Grand Unified Configuration(GUC)パラメータ | 集計期間中に同じプライマリ キー値を持つクエリの平均消費時間。 |
message | text | 返されたエラーメッセージ。 | 該当なし。 |
query_start | timestamptz | クエリが開始された時点。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリが開始された時点。 |
query_date | text | クエリが開始された日付。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリが開始された日付。 |
query | text | クエリで実行された文。 文の長さは最大 51,200 文字です。 SQL 文の長さが 51,200 文字を超える場合、最初の 51,200 文字のみが保持されます。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリで実行された文。 |
result_rows | bigint | 返された行数。 クエリで INSERT 文が実行された場合は、挿入された行数が返されます。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの result_rows フィールドの平均値。 |
result_bytes | bigint | 返されたバイト数。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの result_bytes フィールドの平均値。 |
read_rows | bigint | クエリによって読み取られた行数。 値は正確な値ではありません。 ビットマップ インデックスが使用されている場合、値はクエリによって実際に読み取られた行数と同じではありません。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの read_rows フィールドの平均値。 |
read_bytes | bigint | クエリによって読み取られたバイト数。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの read_bytes フィールドの平均値。 |
affected_rows | bigint | DML 文の影響を受けた行数。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの affected_rows フィールドの平均値。 |
affected_bytes | bigint | DML 文の影響を受けたバイト数。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの affected_bytes フィールドの平均値。 |
memory_bytes | bigint | ノードの累積ピーク メモリ使用量。 値は正確な値ではありません。 このフィールドは、すべての実行ノードでクエリによって消費された累積ピーク メモリ使用量を指定します。 フィールドの値は、クエリで読み取られるデータ量をほぼ反映しています。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの memory_bytes フィールドの平均値。 |
shuffle_bytes | bigint | シャッフルされたバイト数。 値は正確な値ではありません。 フィールドの値は、ネットワーク経由で送信されたデータ量をほぼ反映しています。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの shuffle_bytes フィールドの平均値。 |
cpu_time_ms | bigint | 合計 CPU 時間(ミリ秒)。 値は正確な値ではありません。 このフィールドは、すべての計算タスクによって消費された CPU 時間を指定します。これは、複数の CPU コアの時間の合計です。 このフィールドの値は、基本的に計算タスクの複雑さを反映しています。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの cpu_time_ms フィールドの平均値。 |
physical_reads | bigint | 物理読み取り回数。 このフィールドは、バッチ レコードがディスクから読み取られる回数を指定します。 フィールドの値は、メモリ キャッシュ ミスの回数をほぼ反映しています。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリの physical_reads フィールドの平均値。 |
pid | integer | クエリのプロセス識別子(PID)。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリの PID。 |
application_name | text | クエリを開始したアプリケーションのタイプ。 次の一般的なアプリケーション タイプが含まれます。
Hologres インスタンスに接続されている他のアプリケーションの場合は、接続文字列で | クエリを開始したアプリケーションのタイプ。 |
engine_type | text[] | クエリで使用されるエンジン。 有効な値:
| 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリで使用されるエンジン。 |
client_addr | text | クエリが開始された IP アドレス。 このフィールドは、アプリケーションの出口 IP アドレスを指定します。 値は、アプリケーションの実際の IP アドレスではない場合があります。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリが開始された IP アドレス。 |
table_write | text | データが書き込まれたテーブル。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリでデータが書き込まれたテーブル。 |
table_read | text[] | データが読み取られたテーブル。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリでデータが読み取られたテーブル。 |
session_id | text | クエリ セッションの ID。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリのセッション ID。 |
session_start | timestamptz | クエリ セッションが開始された時点。 このフィールドは、接続が確立された時点を指定します。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリのセッションが開始された時点。 |
command_id | text | コマンドまたは文の ID。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリのコマンドまたは文の ID。 |
optimization_cost | integer | クエリのクエリ実行プランの生成に消費された時間。 実行した SQL 文が複雑な場合、実行プランの生成に時間がかかることがあります。 | 集計期間中に同じプライマリ キー値を持つすべてのクエリのクエリ実行プランの生成に消費された時間。 |
start_query_cost | integer | クエリの開始に消費された時間。 ロックが解放されるか、リソースが解放されるのを待機している場合、クエリの開始に時間がかかることがあります。 | 集計期間中に同じプライマリ キー値を持つクエリの開始に消費された時間。 |
get_next_cost | integer | クエリの実行に消費された時間。 大量のデータを読み取る場合、クエリに時間がかかることがあります。 この場合、ビジネス要件に基づいて SQL 文を最適化できます。 | 集計期間中に同じプライマリ キー値を持つクエリの実行に消費された時間。 |
extended_cost | text | クエリの他の操作に消費された時間。 クエリに消費された合計時間には、optimization_cost、start_query_cost、get_next_cost、および extended_cost フィールドの値が含まれます。
| 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリの時間消費の詳細。 |
plan | text | クエリのクエリ実行プラン。 実行プランには、最大 102,400 文字を含めることができます。 超過した文字は切り捨てられる場合があります。 GUC パラメータ | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリのクエリ実行プラン。 |
statistics | text | クエリに関する実行統計。 統計には、最大 102,400 文字を含めることができます。 超過した文字は切り捨てられる場合があります。 GUC パラメータ | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリに関する実行統計。 |
visualization_info | text | 実行プランに関する視覚化情報。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリのクエリ実行プランに関する視覚化情報。 |
query_detail | text | JSON 形式のクエリに関する拡張情報。 説明 拡張情報には、最大 10,240 文字を含めることができます。 長さが 10,240 文字を超える場合、最初の 10,240 文字のみが保持されます。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリに関する拡張情報。 |
query_extinfo | text[] |
説明 ローカル アカウント、サービスロール(SLR)、またはセキュリティトークンサービス(STS)を使用して Hologres コンソールにログインした場合、AccessKey ID は記録されません。 一時アカウントを使用して Hologres コンソールにログインした場合、一時 AccessKey ID が記録されます。 | 集計期間中に同じプライマリ キー値を持つクエリの中で、最初のクエリに関する拡張情報。 |
calls | INT | 詳細情報が集計されていないため、値は 1 です。 | 集計期間中に同じプライマリ キー値を持つクエリの件数。 |
agg_stats | JSONB | 該当なし。 | 集計期間中に同じプライマリ キー値を持つクエリの duration、memory_bytes、cpu_time_ms、physical_reads、optimization_cost、start_query_cost、および get_next_cost フィールドに対する MIN、MAX、AVG などの集計操作の値。 |
extended_info | JSONB | クエリ キュー や サーバーレス コンピューティング リソース に関する情報など、その他の拡張情報。
| 該当なし。 |
calls フィールドと agg_stats フィールドは、Hologres V3.0.2 の新機能です。
ユーザーにクエリ権限を付与する
承認されたユーザーのみがスロークエリのログをクエリできます。 ユーザーにクエリ権限を付与する場合は、次の項目に注意してください。
ユーザーには、hologres インスタンス内のすべてのデータベースのスロークエリのログをクエリする権限を付与できます。
ユーザーにスーパーユーザー権限を付与します。
Hologres インスタンスのスーパーユーザー権限がユーザーに付与されると、ユーザーは Hologres インスタンス内のすべてのデータベースのスロークエリのログをクエリできます。
ALTER USER "アカウント ID" SUPERUSER;-- アカウント ID をユーザーの Alibaba Cloud アカウント ID に置き換えます。 ユーザーが RAM ユーザーの場合は、アカウント ID の前に p4_ を付けます。
pg_read_all_stats ユーザー グループにユーザーを追加します。
スーパーユーザーに加えて、pg_read_all_stats ユーザー グループのユーザーは、関連する Hologres インスタンス内のすべてのデータベースのスロークエリのログをクエリする権限を持っています。 スーパーユーザーの場合は、このユーザー グループに一般ユーザーを追加できます。 このユーザー グループにユーザーを追加するには、次のいずれかの文を実行します。
GRANT pg_read_all_stats TO "アカウント ID";-- 標準の PostgreSQL 承認モデルを使用して、関連する権限をユーザーに付与します。 CALL spm_grant('pg_read_all_stats', 'アカウント ID'); -- 簡易権限モデル(SPM)を使用して、関連する権限をユーザーに付与します。 CALL slpm_grant('pg_read_all_stats', 'Alibaba Cloud アカウント ID'); -- SLPM を使用して、関連する権限をユーザーに付与します。
ユーザーには、hologres インスタンス内の特定のデータベースのスロークエリのログをクエリする権限を付与できます。
db_admin ユーザー グループのユーザーは、関連データベースのスロークエリのログをクエリする権限を持っています。 スーパーユーザーの場合は、SPM または SLPM を使用して、このユーザー グループに一般ユーザーを追加できます。
CALL spm_grant('<db_name>_admin', 'アカウント ID'); -- SPM を使用して、関連する権限をユーザーに付与します。 CALL slpm_grant('<db_name>.admin', 'アカウント ID'); -- SLPM を使用して、関連する権限をユーザーに付与します。
一般ユーザーは、関連する Alibaba Cloud アカウント内のデータベースで一般ユーザーが開始したスロークエリのログをクエリする権限を持っています。
HoloWeb コンソールでスロークエリのログをクエリする
HoloWeb コンソールでスロークエリのログを視覚的にクエリできます。
過去 7 日間のスロークエリのログは、HoloWeb コンソールでクエリできます。
スーパーユーザーのみが HoloWeb コンソールでスロークエリのログをクエリできます。 関連する権限を持つ一般ユーザーの場合は、SQL 文を実行してスロークエリのログをクエリできます。
HoloWeb コンソールにログインします。 詳細については、「HoloWeb に接続してクエリを実行する」をご参照ください。
上部のナビゲーション バーで、[診断と最適化] をクリックします。
左側のナビゲーション ウィンドウで、[履歴スロークエリ] をクリックします。
[履歴スロークエリ] ページの上部で、クエリ条件を設定します。
履歴スロークエリ ページのパラメータの詳細については、「スロークエリのログをクエリおよび分析する」をご参照ください。
[クエリ] をクリックし、[クエリ傾向分析] セクションと [クエリ] セクションでクエリ結果を表示します。
クエリ傾向分析
クエリ傾向分析セクションには、指定された期間のスロークエリまたは失敗したクエリの傾向が視覚的に表示されます。 これにより、スロークエリと失敗したクエリが頻繁に発生した期間を特定し、問題をまとめてトラブルシューティングできます。
クエリ
クエリ セクションには、スロークエリと失敗したクエリの詳細が表示されます。 クエリ セクションのパラメータの詳細については、「スロークエリのログをクエリおよび分析する」をご参照ください。 また、[列のカスタマイズ] をクリックして、クエリ セクションに表示するフィールドを選択することもできます。
SQL フィンガープリント
Hologres V2.2 以降では、システム テーブル hologres.hg_query_log に digest フィールドが追加され、クエリの SQL フィンガープリントが保存されます。 SELECT、INSERT、DELETE、または UPDATE 文を実行することによって実行されるクエリの場合、システムは MD5 ハッシュ値をクエリの SQL フィンガープリントとして計算します。 これにより、ビジネスのクエリの分類と分析が容易になります。
SQL フィンガープリントは、次のルールに基づいて収集および計算されます。
デフォルトでは、SELECT、INSERT、DELETE、または UPDATE 文を実行することによって実行されるクエリの SQL フィンガープリントのみが収集されます。
INSERT
文を実行してテーブルに定数値を挿入する場合、この文の SQL フィンガープリントは、挿入されるデータの量の影響を受けません。SQL フィンガープリントの計算は、Hologres が SQL 文を処理するために使用するルールと同じ大文字と小文字の区別ルールに従います。
SQL フィンガープリントの計算中に、システムはすべての空白文字を無視し、SQL 文の構造情報のみを考慮します。 空白文字には、スペース、改行、タブが含まれます。
SQL フィンガープリントの計算中に、定数値が SQL フィンガープリントに及ぼす影響は無視されます。
たとえば、
SELECT * FROM t WHERE a > 1;
文の SQL フィンガープリントは、SELECT * FROM t WHERE a > 2;
文の SQL フィンガープリントと同じです。クエリ文に定数で構成される配列が含まれている場合、SQL フィンガープリントの計算は、配列内の要素の数に影響されません。
たとえば、
SELECT * FROM t WHERE a IN (1, 2);
文の SQL フィンガープリントは、SELECT * FROM t WHERE a IN (3, 4, 5);
文の SQL フィンガープリントと同じです。SQL フィンガープリントの計算中に、クエリ内のテーブルは、テーブル名、テーブルが属するデータベースの名前、およびテーブルが属するスキーマの名前によって識別されます。
たとえば、
SELECT * FROM t;
文の SQL フィンガープリントは、前の文のテーブルt
がpublic
スキーマに属している場合にのみ、SELECT * FROM public.t;
文の SQL フィンガープリントと同じです。
スロークエリのログを分析する
hologres.hg_query_log テーブルをクエリすることで、スロークエリのログを取得できます。 このセクションでは、スロークエリのログを分析するためによく使用される SQL 文について説明します。 次の操作を実行できます。
次の文を実行して、スロークエリの総数をクエリします。 デフォルトでは、前月のスロークエリの数が返されます。
SELECT count(*) FROM hologres.hg_query_log;
次の結果が返されます。 結果は、実行時間が指定されたしきい値を超えた 44 件のクエリが前月に開始されたことを示しています。
count ------- 44 (1 row)
次の文を実行して、各ユーザーが開始したスロークエリの数をクエリします。
SELECT usename AS "ユーザー", count(1) as "スロークエリの件数" FROM hologres.hg_query_log GROUP BY usename order by count(1) desc;
次の結果が返されます。
count(1)
関数によって返される値は、各ユーザーが開始したスロークエリの数を示します。ユーザー | スロークエリの件数 -----------------------+----- 1111111111111111 | 27 2222222222222222 | 11 3333333333333333 | 4 4444444444444444 | 2 (4 rows)
次の文を実行して、指定されたスロークエリの詳細をクエリします。
SELECT * FROM hologres.hg_query_log WHERE query_id = '13001450118416xxxx';
次の結果が返されます。 フィールドの詳細については、このトピックの hologres.hg_query_log テーブルのクエリ を参照してください。
usename | status | query_id | datname| command_tag | duration | message | query_start | query_date | query | result_rows | result_bytes | read_rows |read_bytes | affected_rows | affected_bytes | memory_bytes | shuffle_bytes | cpu_time_ms | physical_reads | pid | application_name | engine_type | client_addr | table_write | table_read | session_id | session_start | command_id | optimization_cost | start_query_cost | get_next_cost | extended_cost | plan | statistics | visualization_info | query_detail | query_extinfo -----------------------+---------+--------------------+---------+-------------+----------+---------+------------------------+------------+---------------------------------------------------------------------------------------------------------+-------------+--------------+-----------+------------+---------------+----------------+--------------+---------------+-------------+----------------+---------+------------------+-------------+---------------+-------------+------------+-----------------+------------------------+------------+-------------------+------------------+---------------+---------------+------+------------+--------------------+--------------+--------------- p4_11111111111xxxx | SUCCESS | 13001450118416xxxx | dbname | SELECT | 149 | | 2021-03-30 23:45:01+08 | 20210330 | explain analyze SELECT * FROM tablename WHERE user_id = '20210330010xxxx' limit 1000; | 1000 | 417172 | 0 | 0 | -1 | -1 | 26731376 | 476603616 | 321626 | 0 | 1984913 | psql | {HQE} | 33.41.xxx.xxx | | | 6063475a.1e4991 | 2021-03-30 23:44:26+08 | 0 | 58 | 22 | 67 | | | | | | (1 row)
次の文を実行して、最近の時間範囲(たとえば、過去 10 分間)で最も時間がかかったスロークエリをクエリします。 ビジネス要件に基づいて時間範囲を指定できます。
SELECT status AS "ステータス", duration AS "消費時間(ms)", query_start AS "開始時刻", (read_bytes/1048576)::text || ' MB' AS "読み取りバイト数", (memory_bytes/1048576)::text || ' MB' AS "メモリ", (shuffle_bytes/1048576)::text || ' MB' AS "シャッフル", (cpu_time_ms/1000)::text || ' s' AS "CPU 時間", physical_reads as "物理読み取り", query_id as "クエリ ID", query::char(30) FROM hologres.hg_query_log WHERE query_start >= now() - interval '10 min' ORDER BY duration DESC, read_bytes DESC, shuffle_bytes DESC, memory_bytes DESC, cpu_time_ms DESC, physical_reads DESC LIMIT 100;
次の結果が返されます。
ステータス |消費時間(ms) | 開始時刻 | 読み取りバイト数 | メモリ | シャッフル | CPU 時間 | 物理読み取り | クエリ ID | クエリ ---------+---------+------------------------+--------+-------+---------+---------+------+--------------------+-------------------------------- SUCCESS | 149 | 2021-03-30 23:45:01+08 | 0 MB | 25 MB | 454 MB | 321 s | 0 | 13001450118416xxxx | explain analyze SELECT * FROM SUCCESS | 137 | 2021-03-30 23:49:18+08 | 247 MB | 21 MB | 213 MB | 803 s | 7771 | 13001491818416xxxx | explain analyze SELECT * FROM FAILED | 53 | 2021-03-30 23:48:43+08 | 0 MB | 0 MB | 0 MB | 0 s | 0 | 13001484318416xxxx | SELECT ds::bigint / 0 FROM pub (3 rows)
前日に開始されたクエリの数をクエリします。
次の文を実行して、前日に開始されたクエリの総数をクエリします。
SELECT COUNT(1) FROM ( SELECT DISTINCT t1.digest FROM hologres.hg_query_log t1 WHERE t1.query_start >= CURRENT_DATE - INTERVAL '1 day' AND t1.query_start < CURRENT_DATE AND NOT EXISTS ( SELECT 1 FROM hologres.hg_query_log t2 WHERE t2.digest = t1.digest AND t2.query_start < CURRENT_DATE - INTERVAL '1 day') AND digest IS NOT NULL ) AS a;
次の結果は、前日に合計 10 件のクエリが開始されたことを示しています。
count ------- 10 (1 row)
次の文を実行して、前日に開始された各タイプのクエリの数をクエリします。 クエリ タイプは command_tag によって指定されます。
SELECT a.command_tag, COUNT(1) FROM ( SELECT DISTINCT t1.digest, t1.command_tag FROM hologres.hg_query_log t1 WHERE t1.query_start >= CURRENT_DATE - INTERVAL '1 day' AND t1.query_start < CURRENT_DATE AND NOT EXISTS ( SELECT 1 FROM hologres.hg_query_log t2 WHERE t2.digest = t1.digest AND t2.query_start < CURRENT_DATE - INTERVAL '1 day') AND t1.digest IS NOT NULL) AS a GROUP BY 1 ORDER BY 2 DESC;
次の結果は、前日に 8 件の
INSERT
クエリと 2 件のSELECT
クエリが開始されたことを示しています。command_tag | count ------------+-------- INSERT | 8 SELECT | 2 (2 rows)
次の文を実行して、前日に開始されたクエリの詳細をクエリします。
SELECT a.usename, a.status, a.query_id, a.digest, a.datname, a.command_tag, a.query, a.cpu_time_ms, a.memory_bytes FROM ( SELECT DISTINCT t1.usename, t1.status, t1.query_id, t1.digest, t1.datname, t1.command_tag, t1.query, t1.cpu_time_ms, t1.memory_bytes FROM hologres.hg_query_log t1 WHERE t1.query_start >= CURRENT_DATE - INTERVAL '1 day' AND t1.query_start < CURRENT_DATE AND NOT EXISTS ( SELECT 1 FROM hologres.hg_query_log t2 WHERE t2.digest = t1.digest AND t2.query_start < CURRENT_DATE - INTERVAL '1 day' ) AND t1.digest IS NOT NULL ) AS a;
次の結果が返されます。
usename |status |query_id |digest |datname|command_tag |query |cpu_time_ms |memory_bytes -----------------+--------+--------------------+------------------------------------+-------+-------------+-----------------------------------+--------------+-------------- 111111111111xxxx |SUCCESS |100100425827776xxxx |md58cf93d91c36c6bc9998add971458ba1a |dbname |INSERT |INSERT INTO xxx SELECT * FROM xxx | 1748| 898808596 111111111111xxxx |SUCCESS |100100425827965xxxx |md5f7e87e2c9e0b3d9eddcd6b3bc7f04b3b |dbname |INSERT |INSERT INTO xxx SELECT * FROM xxx | 59891| 6819529886 111111111111xxxx |SUCCESS |100100425829654xxxx |md55612dc09d2d81074fd5deed1aa3eca9b |dbname |INSERT |INSERT INTO xxx SELECT * FROM xxx | 3| 2100039 111111111111xxxx |SUCCESS |100100425829664xxxx |md58d3bf67fbdf2247559bc916586d40011 |dbname |INSERT |INSERT INTO xxx SELECT * FROM xxx | 10729| 2052861937 111111111111xxxx |SUCCESS |100100425830099xxxx |md503bd45d6b2d7701c2617d079b4d55a10 |dbname |INSERT |INSERT INTO xxx SELECT * FROM xxx | 2196| 897948034 111111111111xxxx |SUCCESS |100100425830186xxxx |md5c62169eaf3ea3a0c59bdc834a8141ac4 |dbname |INSERT |INSERT INTO xxx SELECT * FROM xxx | 5268| 1734305972 111111111111xxxx |SUCCESS |100100425830448xxxx |md59aa0c73b24c9c9eba0b34c8fdfc23bb0 |dbname |INSERT |INSERT INTO xxx SELECT * FROM xxx | 2| 2098402 111111111111xxxx |SUCCESS |100100425830459xxxx |md57d22c1d37b68984e9472f11a4c9fd04e |dbname |INSERT |INSERT INTO xxx SELECT * FROM xxx | 113| 76201984 111111111111xxxx |SUCCESS |100100525468694xxxx |md5ac7d6556fae123e9ea9527d8f1c94b1c |dbname |SELECT |SELECT * FROM xxx limit 200 | 6| 1048576 111111111111xxxx |SUCCESS |100101025538840xxxx |md547d09cdad4d5b5da74abaf08cba79ca0 |dbname |SELECT |SELECT * FROM xxx limit 200 |\N |\N (10 rows)
次の文を実行して、前日の各時間で開始されたクエリの傾向をクエリします。
SELECT to_char(a.query_start, 'HH24') AS query_start_hour, a.command_tag, COUNT(1) FROM ( SELECT DISTINCT t1.query_start, t1.digest, t1.command_tag FROM hologres.hg_query_log t1 WHERE t1.query_start >= CURRENT_DATE - INTERVAL '1 day' AND t1.query_start < CURRENT_DATE AND NOT EXISTS ( SELECT 1 FROM hologres.hg_query_log t2 WHERE t2.digest = t1.digest AND t2.query_start < CURRENT_DATE - INTERVAL '1 day' ) AND t1.digest IS NOT NULL ) AS a GROUP BY 1, 2 ORDER BY 3 DESC;
次の結果は、前日の 11 時間目に 1 件の SELECT クエリが開始され、13 時間目に別の SELECT クエリが開始され、21 時間目に 8 件の INSERT クエリが開始されたことを示しています。
query_start_hour |command_tag |count ------------------+-------------+----- 21 |INSERT | 8 11 |SELECT | 1 13 |SELECT | 1 (3 rows)
次の文を実行して、スロークエリを分類します。
SELECT digest, command_tag, count(1) FROM hologres.hg_query_log WHERE query_start >= CURRENT_DATE - INTERVAL '1 day' AND query_start < CURRENT_DATE GROUP BY 1,2 ORDER BY 3 DESC;
次の文を実行して、前日に最大の CPU オーバーヘッドを生成した上位 10 件のクエリをクエリします。
SELECT digest, avg(cpu_time_ms) FROM hologres.hg_query_log WHERE query_start >= CURRENT_DATE - INTERVAL '1 day' AND query_start < CURRENT_DATE AND digest IS NOT NULL AND usename != 'system' AND cpu_time_ms IS NOT NULL GROUP BY 1 ORDER BY 2 DESC LIMIT 10;
次の文を実行して、前週で最大のメモリ リソースを占有した上位 10 件のクエリをクエリします。 メモリは memory_bytes によって指定されます。
SELECT digest, avg(memory_bytes) FROM hologres.hg_query_log WHERE query_start >= CURRENT_DATE - INTERVAL '7 day' AND query_start < CURRENT_DATE AND digest IS NOT NULL AND memory_bytes IS NOT NULL GROUP BY 1 ORDER BY 2 DESC LIMIT 10;
次の文を実行して、過去 3 時間のそれぞれで開始されたスロークエリのアクセス量とデータ読み取り量をクエリします。 これにより、各時間のデータ量の変更を判断できます。
SELECT date_trunc('hour', query_start) AS query_start, count(1) AS query_count, sum(read_bytes) AS read_bytes, sum(cpu_time_ms) AS cpu_time_ms FROM hologres.hg_query_log WHERE query_start >= now() - interval '3 h' GROUP BY 1;
次の文を実行して、過去 3 時間のデータアクセス量と比較のために前日の同じ期間のデータアクセス量をクエリします。 これにより、前日の同じ期間と比較してデータアクセス量が変化するかどうかを判断できます。
SELECT query_date, count(1) AS query_count, sum(read_bytes) AS read_bytes, sum(cpu_time_ms) AS cpu_time_ms FROM hologres.hg_query_log WHERE query_start >= now() - interval '3 h' GROUP BY query_date UNION ALL SELECT query_date, count(1) AS query_count, sum(read_bytes) AS read_bytes, sum(cpu_time_ms) AS cpu_time_ms FROM hologres.hg_query_log WHERE query_start >= now() - interval '1d 3h' AND query_start <= now() - interval '1d' GROUP BY query_date;
次の文を実行して、最近の時間範囲(たとえば、過去 10 分間)で異なるクエリ ステージで最も時間がかかったスロークエリをクエリします。 ビジネス要件に基づいて時間範囲を指定できます。
SELECT status AS "ステータス", duration AS "消費時間(ms)", optimization_cost AS "最適化時間(ms)", start_query_cost AS "起動時間(ms)", get_next_cost AS "実行時間(ms)", duration - optimization_cost - start_query_cost - get_next_cost AS "その他(ms)", query_id AS "クエリ ID", query::char(30) FROM hologres.hg_query_log WHERE query_start >= now() - interval '10 min' ORDER BY duration DESC, start_query_cost DESC, optimization_cost, get_next_cost DESC, duration - optimization_cost - start_query_cost - get_next_cost DESC LIMIT 100;
次の結果が返されます。
ステータス | 消費時間(ms) | 最適化時間(ms) | 起動時間(ms) | 実行時間(ms) | その他(ms) | クエリ ID | クエリ ---------+----------+--------------+--------------+--------------+--------------+--------------------+-------------------------------- SUCCESS | 4572 | 521 | 320 | 3726 | 5 | 6000260625679xxxx | -- /* user: wang ip: xxx.xx.x SUCCESS | 1490 | 538 | 98 | 846 | 8 | 12000250867886xxxx | -- /* user: lisa ip: xxx.xx.x SUCCESS | 1230 | 502 | 95 | 625 | 8 | 26000512070295xxxx | -- /* user: zhang ip: xxx.xx. (3 rows)
次の文を実行して、最初に失敗したクエリをクエリします。
SELECT status AS "ステータス", regexp_replace(message, '\n', ' ')::char(150) AS "エラーメッセージ", duration AS "消費時間(ms)", query_start AS "開始時刻", query_id AS "クエリ ID", query::char(100) AS "クエリ" FROM hologres.hg_query_log WHERE query_start BETWEEN '2021-03-25 17:00:00'::timestamptz AND '2021-03-25 17:42:00'::timestamptz + interval '2 min' AND status = 'FAILED' ORDER BY query_start ASC LIMIT 100;
次の結果が返されます。
ステータス | エラーメッセージ | 消費時間(ms) | 開始時刻 | クエリ ID | クエリ --------+--------------------------------------------------------------------------------------------------------------------------------------------------------+-------+------------------------+-------------------+------- FAILED | Query:[1070285448673xxxx] code: kActorInvokeError msg: "[holo_query_executor.cc:330 operator()] HGERR_code XX000 HGERR_msge internal error: status { c | 1460 | 2021-03-25 17:28:54+08 | 1070285448673xxxx | S... FAILED | Query:[1016285560553xxxx] code: kActorInvokeError msg: "[holo_query_executor.cc:330 operator()] HGERR_code XX000 HGERR_msge internal error: status { c | 131 | 2021-03-25 17:28:55+08 | 1016285560553xxxx | S... (2 rows)
スロークエリのログのライフサイクルを変更する
Hologres V3.0.27 以降では、スロークエリのログのライフサイクルを変更できます。 次の SQL 文を実行して、データベース レベルで変更を加えることができます。
ALTER DATABASE <db_name> SET hg_query_log_retention_time_sec = 2592000;
パラメータ値の範囲は 259200 ~ 2592000 秒で、ライフサイクルは 3 ~ 30 日です。
変更されたライフサイクルは、新しく追加されたログにのみ適用されます。 既存のログは、以前の設定に従います。
変更されたライフサイクルは、新しい接続に対してのみ有効になります。
このパラメータを設定してライフサイクルを指定すると、期限切れのログは非同期ではなくすぐにクリーンアップされます。
スロークエリのログをエクスポートする
Hologres では、INSERT 文を実行して、スロークエリのログを hologres.hg_query_log テーブルからカスタム内部テーブルまたは MaxCompute 外部テーブルや Object Storage Service (OSS) 外部テーブルなどの外部テーブルにエクスポートできます。
使用上の注意
スロークエリのログを正しく効率的にエクスポートするには、次の項目に注意してください。
INSERT INTO ... SELECT ... FROM hologres.hg_query_log;
文の実行に使用されるアカウントは、hologres.hg_query_log
テーブルへのアクセス権限を持っている必要があります。 詳細については、「ユーザーにクエリ権限を付与する」をご参照ください。 インスタンスのすべてのスロークエリのログをエクスポートするには、INSERT
文の実行に使用されるアカウントが、スーパーユーザー権限または pg_read_all_stats 権限を持っている必要があります。 そうしないと、hologres.hg_query_log
テーブルの一部のデータのみをクエリおよびエクスポートできます。hologres.hg_query_log テーブルの query_start フィールドにはインデックスが設定されています。 特定の期間内に生成されたデータをエクスポートする場合は、インデックスを使用してデータをクエリします。 これにより、パフォーマンスが向上し、リソース消費が削減されます。
インデックスを使用してデータをクエリする場合は、
query_start
フィールドにネストされた式を使用しないでください。 そうしないと、インデックスが機能しない場合があります。 たとえば、WHERE to_char(query_start, 'yyyymmdd') = '20220101';
をWHERE query_start >= to_char('20220101', 'yyyy-mm-dd') and query_start < to_char('20220102', 'yyyy-mm-dd');
に置き換えることをお勧めします。
例 1:スロークエリのログを Hologres 内部テーブルにエクスポートする
Hologres で次の文を実行して、スロークエリのログを query_log_download 内部テーブルにエクスポートします。
--Hologres SQL CREATE TABLE query_log_download ( usename text, status text, query_id text, datname text, command_tag text, duration integer, message text, query_start timestamp with time zone, query_date text, query text, result_rows bigint, result_bytes bigint, read_rows bigint, read_bytes bigint, affected_rows bigint, affected_bytes bigint, memory_bytes bigint, shuffle_bytesbigint, cpu_time_ms bigint, physical_reads bigint, pid integer, application_name text, engine_type text[], client_addr text, table_write text, table_read text[], session_id text, session_start timestamp with time zone, trans_id text, command_id text, optimization_cost integer, start_query_cost integer, get_next_cost integer, extended_cost text, plan text, statistics text, visualization_info text, query_detail text, query_extinfo text[] ); INSERT INTO query_log_download SELECT usename, status, query_id, datname, command_tag, duration, message, query_start, query_date, query, result_rows, result_bytes, read_rows, read_bytes, affected_rows, affected_bytes, memory_bytes, shuffle_bytes, cpu_time_ms, physical_reads, pid, application_name, engine_type, client_addr, table_write, table_read, session_id, session_start, trans_id, command_id, optimization_cost, start_query_cost, get_next_cost, extended_cost, plan, statistics, visualization_info, query_detail, query_extinfo FROM hologres.hg_query_log WHERE query_start >= '2022-08-03' AND query_start < '2022-08-04';
例 2:スロークエリのログを MaxCompute 外部テーブルにエクスポートする
MaxCompute で次の文を実行して、スロークエリのログをエクスポートする MaxCompute テーブルを作成します。
CREATE TABLE if NOT EXISTS mc_holo_query_log ( username STRING COMMENT 'クエリを開始したユーザーの名前。' ,status STRING COMMENT 'クエリのステータス。 値は、クエリが成功したかどうかを示します。' ,query_id STRING COMMENT 'クエリの ID。' ,datname STRING COMMENT 'クエリ対象のデータベースの名前。' ,command_tag STRING COMMENT 'クエリで実行された文のタイプ。' ,duration BIGINT COMMENT 'クエリに消費された時間(ミリ秒)。' ,message STRING COMMENT '返されたエラーメッセージ。' ,query STRING COMMENT 'クエリで実行された文。' ,read_rows BIGINT COMMENT 'クエリによって読み取られた行数。' ,read_bytes BIGINT COMMENT 'クエリによって読み取られたバイト数。' ,memory_bytes BIGINT COMMENT '単一ノードのピーク メモリ使用量。 値は正確な値ではありません。' ,shuffle_bytes BIGINT COMMENT 'シャッフルされたバイト数。 値は正確な値ではありません。' ,cpu_time_ms BIGINT COMMENT '合計 CPU 時間(ミリ秒)。 値は正確な値ではありません。' ,physical_reads BIGINT COMMENT '物理読み取り回数。' ,application_name STRING COMMENT 'クエリを開始したアプリケーションのタイプ。' ,engine_type ARRAY<STRING> COMMENT 'クエリで使用されるエンジン。' ,table_write STRING COMMENT 'データが書き込まれたテーブル。' ,table_read ARRAY<STRING> COMMENT 'データが読み取られたテーブル。' ,plan STRING COMMENT 'クエリのクエリ実行プラン。' ,optimization_cost BIGINT COMMENT 'クエリのクエリ実行プランの生成に消費された時間。' ,start_query_cost BIGINT COMMENT 'クエリの開始に消費された時間。' ,get_next_cost BIGINT COMMENT 'クエリの実行に消費された時間。' ,extended_cost STRING COMMENT 'クエリの他の操作に消費された時間。' ,query_detail STRING COMMENT 'JSON 形式のクエリに関する拡張情報。' ,query_extinfo ARRAY<STRING> COMMENT '配列形式のクエリに関する拡張情報。' ,query_start STRING COMMENT 'クエリが開始された時点。' ,query_date STRING COMMENT 'クエリが開始された日付。' ) COMMENT 'hologres インスタンス クエリ ログ daily' PARTITIONED BY ( ds STRING COMMENT '統計日' ) LIFECYCLE 365; ALTER TABLE mc_holo_query_log ADD PARTITION (ds=20220803);
Hologres で次の文を実行して、スロークエリのログを MaxCompute 外部テーブルにエクスポートします。
IMPORT FOREIGN SCHEMA project_name LIMIT TO (mc_holo_query_log) FROM SERVER odps_server INTO public; INSERT INTO mc_holo_query_log SELECT usename AS username, status, query_id, datname, command_tag, duration, message, query, read_rows, read_bytes, memory_bytes, shuffle_bytes, cpu_time_ms, physical_reads, application_name, engine_type, table_write, table_read, plan, optimization_cost, start_query_cost, get_next_cost, extended_cost, query_detail, query_extinfo, query_start, query_date, '20220803' FROM hologres.hg_query_log WHERE query_start >= '2022-08-03' AND query_start < '2022-08-04';
設定項目
Hologres は、スロークエリのログの収集を設定できる次の設定項目を提供します。
log_min_duration_statement
説明
この設定項目の変更は、新しいクエリに対してのみ有効になります。 収集済みのクエリについては、元の値が有効になります。
スーパーユーザーのみがこの設定項目を変更できます。
この設定項目を
-1
に設定すると、スロークエリのログは収集されません。 この設定項目を正の値に設定した場合、最小値は 100 ミリ秒です。例
250 ミリ秒
以上を消費するスロークエリのログをシステムが収集できるようにします。-- データベースのスーパーユーザーとして次の文を実行します。 ALTER DATABASE dbname SET log_min_duration_statement = '250ms'; -- セッションの一般ユーザーとして次の文を実行します。 SET log_min_duration_statement = '250ms';
この設定項目は、スロークエリに消費される時間のしきい値を指定するために使用されます。 デフォルトでは、Hologres は 100 ミリ秒以上を消費するスロークエリのログを収集し、1 秒以上を消費するクエリのみがクエリ結果に表示されます。 この設定項目を設定して期間を変更できます。 次の項目に注意してください。
log_min_duration_query_stats
説明
この設定項目の変更は、新しいクエリに対してのみ有効になります。 収集済みのクエリについては、元の値が有効になります。
この設定項目を
-1
に設定すると、スロークエリに関する実行統計は収集されません。このような統計には、大きなストレージ スペースが必要です。 Hologres が大量の実行統計を収集する場合、スロークエリのログのクエリと分析が遅くなる可能性があります。 したがって、一般的なシナリオでは、少なくとも 10 秒のしきい値を指定することをお勧めします。 特定の問題をトラブルシューティングする場合にのみ、10 秒未満のしきい値を指定します。
例
20 秒以上を消費するスロークエリに関する実行統計をシステムが収集できるようにします。
-- データベースのスーパーユーザーとして次の文を実行します。 ALTER DATABASE dbname SET log_min_duration_query_stats = '20s'; -- セッションの一般ユーザーとして次の文を実行します。 SET log_min_duration_query_stats = '20s';
この設定項目は、実行統計の収集のためにクエリに消費される時間のしきい値を指定するために使用されます。 デフォルトでは、Hologres は 10 秒以上を消費するスロークエリに関する実行統計を収集します。 次の項目に注意してください。
log_min_duration_query_plan
説明
この設定項目の変更は、新しいクエリに対してのみ有効になります。 収集済みのクエリについては、元の値が有効になります。
スロークエリに消費される時間が指定された値以上の場合、スロークエリのクエリ実行プランが収集されます。
デフォルトでは、
EXPLAIN
文を実行してクエリ実行プランをリアルタイムでクエリできるため、このようなデータを収集する必要はありません。この設定項目を
-1
に設定すると、スロークエリのクエリ実行プランは収集されません。例
10 秒以上を消費するスロークエリのクエリ実行プランをシステムが収集できるようにします。
-- データベースのスーパーユーザーとして次の文を実行します。 ALTER DATABASE dbname SET log_min_duration_query_plan = '10s'; -- セッションの一般ユーザーとして次の文を実行します。 SET log_min_duration_query_plan = '10s';
この設定項目は、実行プランの収集のためにクエリに消費される時間のしきい値を指定するために使用されます。 デフォルトでは、Hologres は 10 秒以上を消費するスロークエリのクエリ実行プランを表示します。 次の項目に注意してください。
よくある質問
問題の説明:
Hologres V1.1 では、クエリされた行数や返された行数などの詳細な統計は、クエリされたスロークエリのログでは返されません。
原因:
収集されたスロークエリのログは不完全です。
解決策:
Hologres V1.1.36 ~ Hologres V1.1.49 では、次の文を実行して GUC パラメータを設定できます。これにより、システムは完全なスロークエリのログを返すことができます。 完全なスロークエリのログは、Hologres V1.1.49 以降で直接返されます。
説明Hologres インスタンスのバージョンが V1.1.36 より前の場合、Hologres インスタンスを手動でアップグレードするか、Hologres DingTalk グループに参加してテクニカル サポートを受けてください。 詳細については、「インスタンスのアップグレード」および「Hologres のオンライン サポートを受ける」をご参照ください。
-- (推奨)データベース レベルで GUC パラメータを設定します。 データベースごとに次の文を 1 回だけ実行する必要があります。 ALTER databse <db_name> SET hg_experimental_force_sync_collect_execution_statistics = ON; -- セッション レベルで GUC パラメータを設定します。 SET hg_experimental_force_sync_collect_execution_statistics = ON;
db_name パラメータは、データベースの名前を指定します。
参考資料
インスタンス内のクエリの診断と管理方法の詳細については、「クエリの管理」をご参照ください。