Hologres インスタンスの応答が遅い場合やクエリの実行に時間がかかる場合、スロークエリログが問題の特定と診断に役立ちます。このトピックでは、hologres.hg_query_log テーブルをクエリする方法、キーフィールドを解釈する方法、および診断 SQL を使用してパフォーマンスの問題を特定する方法について説明します。
バージョンガイド
| バージョン | 変更 |
|---|---|
| V0.10 | スロークエリログを導入しました。失敗したクエリのログには、ランタイム統計 (メモリ、ディスク読み取り、データ読み取り量、CPU 時間、または query_stats) は含まれません。 |
| V2.2 | hg_query_log に digest 列 (SQL フィンガープリント) を追加しました。 |
| V2.2.7 | log_min_duration_statement のデフォルト値を 1,000 ms から 100 ms に変更しました。 |
| V3.0.2 | 100 ms 未満で実行される DML および DQL 操作の集計レコードを追加しました。さらに、calls フィールドと agg_stats フィールドを追加しました。 |
| V3.0.27 | hg_query_log_retention_time_sec を使用してログ保持期間を変更できるようになりました。 |
この機能を使用するには、Hologres V0.10 以降が必要です。インスタンスバージョンを確認するには、Hologres コンソールのインスタンスの詳細ページに移動します。以前のインスタンスをアップグレードするには、「Common upgrade preparation errors」を参照するか、Hologres サポートにお問い合わせください。詳細については、「How do I get more online support?」をご参照ください。
制限
スロークエリログは、デフォルトで 1 か月 間保持されます。
1 回のクエリで返されるスロークエリ ログ エントリは最大 10,000 件です。一部のフィールドには長さの制限があります。フィールドの説明については、
hg_query_logテーブルのセクションを参照してください。スロークエリログは Hologres メタデータウェアハウスの一部です。スロークエリログの検索が失敗してもビジネスクエリに影響はなく、ログの可用性は Hologres のサービスレベルアグリーメント (SLA) の対象外です。
仕組み
Hologres は、スロークエリログを hologres.hg_query_log システムテーブルに保存します。このテーブルには、完了した SQL ステートメントのみが記録され、まだ実行中のクエリはテーブルに書き込まれません。この動作は、V2、V3、およびそれ以降のバージョンで一貫しています。
記録される内容:
V0.10 へのアップグレード後:実行時間が 100 ms を超える DML クエリ、およびすべての DDL 操作。
V3.0.2 以降:100 ms を超えるクエリの詳細なレコードに加えて、100 ms 未満で完了する DQL および DML クエリの集計レコードも書き込まれます。
集計の仕組み (V3.0.2 以降):
高速なクエリ (100 ms 未満) の場合、システムは同じ SQL フィンガープリント (digest) を共有する、成功した DQL および DML クエリをグループ化します。集計キーは、server_addr、usename、datname、warehouse_id、application_name、およびdigest です。各接続は、1 分あたり 1 つの集計レコードをフラッシュします。
hg_query_log テーブル
このテーブルには 2 種類のレコードがあり、同じスキーマを共有しますが、セマンティクスが異なります。
| フィールド | データ型 | 詳細レコード (100 ms 超) | 集計レコード (100 ms 未満) |
|---|---|---|---|
usename | text | クエリを実行したユーザー名。 | クエリを実行したユーザー名。 |
status | text | SUCCESS または FAILED。 | 常に SUCCESS (成功したクエリのみが集計されるため)。 |
query_id | text | 一意のクエリ ID。失敗したクエリには常に query_id がありますが、成功したクエリにはない場合があります。 | 同じ集計キーを持つ集計期間内の最初のクエリの query_id。 |
digest | text | SQL フィンガープリント (MD5 ハッシュ)。V2.2 で追加されました。詳細については、「SQL フィンガープリント」をご参照ください。 | SQL フィンガープリント。 |
datname | text | データベース名。 | データベース名。 |
command_tag | text | クエリタイプ: DML (COPY, DELETE, INSERT, SELECT, UPDATE)、DDL (ALTER TABLE, BEGIN, COMMENT, COMMIT, CREATE FOREIGN TABLE, CREATE TABLE, DROP FOREIGN TABLE, DROP TABLE, IMPORT FOREIGN SCHEMA, ROLLBACK, TRUNCATE TABLE)、またはその他 (CALL, CREATE EXTENSION, EXPLAIN, GRANT, SECURITY LABEL)。 | 集計期間内の最初のクエリの command_tag。 |
warehouse_id | integer | クエリに使用された仮想ウェアハウス ID。 | 集計期間内の最初のクエリの仮想ウェアハウス ID。 |
warehouse_name | text | クエリに使用された仮想ウェアハウス名。 | 集計期間内の最初のクエリの仮想ウェアハウス名。 |
warehouse_cluster_id | integer | V3.0.2 で追加されました。仮想ウェアハウス内のクラスター ID。クラスター ID は 1 から始まります。 | 集計期間内の最初のクエリのクラスター ID。 |
duration | integer | クエリの総所要時間 (ミリ秒単位)。後述する 3 つのステージで構成されます。 | 集計期間内の平均所要時間。 |
message | text | 失敗したクエリのエラーメッセージ。 | 空。 |
query_start | timestamptz | クエリの開始時刻。 | 集計期間内の最初のクエリの query_start。 |
query_date | text | クエリの開始日。 | 集計期間内の最初のクエリの query_date。 |
query | text | クエリテキスト。最大 51,200 文字。長いクエリは切り捨てられます。 | 集計期間内の最初のクエリのクエリテキスト。 |
result_rows | bigint | 返された行数。INSERT の場合は、挿入された行数。 | 平均値。 |
result_bytes | bigint | 返されたバイト数。 | 平均値。 |
read_rows | bigint | 読み取られた行数 (概算値です。ビットマップインデックスが使用される場合、実際にスキャンされた行数と異なることがあります)。 | 平均値。 |
read_bytes | bigint | 読み取られたバイト数。 | 平均値。 |
affected_rows | bigint | DML ステートメントによって影響を受けた行数。 | 平均値。 |
affected_bytes | bigint | DML ステートメントによって影響を受けたバイト数。 | 平均値。 |
memory_bytes | bigint | すべてのノードにわたる累積ピークメモリ使用量 (概算値です)。クエリによって読み取られたデータ量を反映します。 | 平均値。 |
shuffle_bytes | bigint | ネットワーク経由でシャッフルされた推定バイト数。 | 平均値。 |
cpu_time_ms | bigint | すべての計算タスクにわたる合計 CPU 時間 (ミリ秒単位) (概算値です)。クエリの複雑さを反映します。 | 平均値。 |
physical_reads | bigint | ディスクから読み取られたレコードバッチの数。キャッシュミス の頻度を反映します。 | 平均値。 |
pid | integer | クエリサービスのプロセス ID。 | 集計期間内の最初のクエリのプロセス ID。 |
application_name | text | アプリケーション識別子。「application_name の値」をご参照ください。 | アプリケーションタイプ。 |
engine_type | text[] | 使用された実行エンジン。「エンジンの種類」をご参照ください。 | 集計期間内の最初のクエリのエンジン。 |
client_addr | text | ソース 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 | クエリ実行計画の生成時間 (ms)。値が高い場合は、SQL ステートメントが複雑であることを示します。 | 平均計画生成時間。 |
start_query_cost | integer | クエリの起動時間 (ms)。値が高い場合は、クエリがロックまたはリソースを待機していることを示します。 | 平均起動時間。 |
get_next_cost | integer | クエリの実行時間 (ms)。値が高い場合は、計算量が大きく、実行に時間がかかることを示します。 | 平均実行時間。 |
extended_cost | text | その他のタイミングの詳細。これには、build_dag (計算用の有向非巡回グラフ (DAG) を構築する時間。値が高い場合は、外部テーブルのメタデータアクセスが遅いことを示します)、prepare_reqs (実行エンジンのリクエストを準備する時間。値が高い場合は、シャードアドレス解決 が遅いことを示します)、およびサーバーレス固有のフィールド (serverless_allocated_cores、serverless_allocated_workers、serverless_resource_used_time_ms) が含まれます。 | 集計期間内の最初のクエリの拡張コスト。 |
plan | text | クエリ実行計画。最大 102,400 文字。長い計画は切り捨てられます。この動作は log_min_duration_query_plan によって制御されます。 | 集計期間内の最初のクエリの実行計画。 |
statistics | text | クエリ実行統計。最大 102,400 文字。この動作は log_min_duration_query_stats によって制御されます。 | 集計期間内の最初のクエリの実行統計。 |
visualization_info | text | クエリ計画の可視化データ。 | 集計期間内の最初のクエリの可視化データ。 |
query_detail | text | JSON 形式の拡張クエリ情報。最大 10,240 文字。長い値は切り捨てられます。 | 集計期間内の最初のクエリの拡張情報。 |
query_extinfo | text[] | 配列形式の拡張クエリ情報。サーバーレスクエリには serverless_computing が含まれます。V2.0.29 以降では、アカウントの AccessKey ID も記録します。注: AccessKey ID は、ローカルアカウント、サービスにリンクされたロール (SLR)、または Security Token Service (STS) ログオンでは記録されません。一時的なアカウントの場合、一時的な AccessKey ID のみが記録されます。 | 集計期間内の最初のクエリの拡張情報。 |
calls | integer | 1詳細レコードの場合は常に (集計なし)。V3.0.2 で追加されました。 | 集計期間内に同じ集計キーを持つクエリの数。 |
agg_stats | jsonb | 空。V3.0.2 で追加されました。 | 数値フィールド (duration、memory_bytes、cpu_time_ms、physical_reads、optimization_cost、start_query_cost、get_next_cost) の MIN、MAX、および AVG 統計。 |
extended_info | jsonb | クエリキューとサーバーレスコンピューティングに関する拡張情報。「extended_info の値」をご参照ください。 | 空。 |
duration の内訳
duration フィールドはクエリの総時間を表し、3 つのステージで構成されます。
| ステージ | フィールド | 意味 | 値が高い場合 |
|---|---|---|---|
| 計画生成 | optimization_cost | 実行計画をコンパイルする時間 | SQL ステートメントが複雑 |
| 起動 | start_query_cost | 実行が開始されるまでの時間 | ロックまたはリソースを待機している |
| 実行 | get_next_cost | クエリを実行する時間 | 計算量が大きく、実行に時間がかかる |
これら 3 つのステージ以外の、より詳細な所要時間については、extended_cost を参照してください。
application_name の値
| ソース | フォーマット |
|---|---|
| Realtime Compute for Apache Flink (VVR) | {client_version}_ververica-connector-hologres |
| オープンソース Flink | {client_version}_hologres-connector-flink |
| DataWorks オフライン読み取り同期 | datax_{jobId} |
| DataWorks オフライン書き込み同期 | {client_version}_datax_{jobId} |
| DataWorks リアルタイム同期 | {client_version}_streamx_{jobId} |
| HoloWeb | holoweb |
| MaxCompute 外部テーブルアクセス | MaxCompute |
| Auto Analyze | AutoAnalyze |
| Quick BI | QuickBI_public_{version} |
| DataWorks スケジューリング | {client_version}_dwscheduler_{tenant_id}_{scheduler_id}_{scheduler_task_id}_{bizdate}_{cyctime}_{scheduler_alisa_id} |
| Data Security Guard | dsg |
その他のアプリケーションについては、接続文字列で application_name を明示的に設定してください。
エンジンの種類
| エンジン | 説明 |
|---|---|
| HQE | Hologres 独自のエンジン。ほとんどのクエリは、高い実行効率のために HQE を使用します。 |
| PQE | PostgreSQL エンジン。PQE が表示される場合、一部の SQL 演算子は HQE でネイティブにサポートされていません。「クエリパフォーマンスの最適化」で説明されているようにこれらを書き換えると、パフォーマンスが向上する場合があります。 |
| FixedQE | Fixed Plan の実行エンジン。ポイント読み取り、ポイント書き込み、PrefixScan などのサービングタイプの SQL を効率的に処理します。以前は SDK と呼ばれていました (V2.2 で改名)。詳細については、「Fixed Plan で SQL 実行を高速化」をご参照ください。 |
| PG | システムテーブルに対するメタデータクエリのためのフロントエンドのローカル計算。ユーザーテーブルのデータは読み取りません。DDL ステートメントも PG を使用します。 |
extended_info の値
extended_info フィールドには、サーバーレスコンピューティング実行のソースが記録されます。
serverless_computing_sourceの値 | 意味 |
|---|---|
user_submit | クエリは、クエリキューとは無関係に、サーバーレスリソースで実行するために手動で送信されました。 |
query_queue | 指定されたクエリキュー内のすべてのクエリは、サーバーレスリソースで実行されます。「サーバーレスコンピューティングリソースを使用してクエリキュー内のクエリを実行する」をご参照ください。 |
query_queue_rerun | クエリは、クエリキューの大規模クエリ制御機能によって、サーバーレスリソースで自動的に再実行されました。「大規模クエリ制御」をご参照ください。 |
serverless_computing_source が query_queue_rerun の場合、再実行されたステートメントの元のクエリ ID を示す query_id_of_triggered_rerun フィールドも表示されます。
前提条件
スロークエリログを表示するには、次のいずれかの権限が必要です。
[インスタンス内のすべてのデータベースのログを表示する場合:]
スーパーユーザー: 次のコマンドを実行します。
Alibaba Cloud account IDを実際のユーザー名に置き換えてください。 RAM ユーザーの場合は、p4_AccountID(RAM ユーザー名ではなく、アカウント ID) を使用してください。ALTER USER "Alibaba Cloud account ID" SUPERUSER;pg_read_all_stats グループ (スーパーユーザー以外の場合): スーパーユーザーに連絡し、このグループへの追加を依頼してください。
-- 標準 PostgreSQL 権限付与 GRANT pg_read_all_stats TO "Alibaba Cloud account ID"; -- 簡易権限モデル (SPM) CALL spm_grant('pg_read_all_stats', 'Alibaba Cloud account ID'); -- スキーマレベル権限モデル (SLPM) CALL slpm_grant('pg_read_all_stats', 'Alibaba Cloud account ID');
[現在のデータベースのログのみを表示する場合:]
SPM または SLPM を有効にし、ユーザーを db_admin ロールに追加します。
-- SPM
CALL spm_grant('<db_name>_admin', 'Alibaba Cloud account ID');
-- SLPM
CALL slpm_grant('<db_name>.admin', 'Alibaba Cloud account ID');一般ユーザー は、追加の設定なしで、現在のデータベース内の自分自身のクエリのみを表示できます。
スロークエリログの表示
Hologres では、スロークエリログを表示する方法が 2 つあります。視覚的な探索には HoloWeb を使用し、カスタムフィルター、時間範囲、エクスポートには SQL を使用します。
| 方法 | 最適な用途 | 制約 |
|---|---|---|
| HoloWeb | 視覚的な探索と傾向分析 | スーパーユーザーのみ。過去 7 日間のみ |
SQL (hologres.hg_query_log テーブル) | カスタム時間範囲、フィルタリング、エクスポート | 適切な権限が必要 |
HoloWeb での表示
HoloWeb コンソールにログインします。
上部ナビゲーションバーで、[診断と最適化] をクリックします。
左側のナビゲーションウィンドウで、[履歴スロークエリ] をクリックします。
[履歴スロークエリ] ページの上部でクエリ条件を設定します。パラメーターの説明については、「Historical Slow Queries」をご参照ください。
[検索] をクリックします。結果は次の 2 つの領域に表示されます。
[クエリ傾向分析]:時間経過に伴うスロークエリと失敗したクエリの頻度を表示し、問題のある期間を特定するのに役立ちます。
[クエリ]:各スロークエリまたは失敗したクエリの詳細情報を一覧表示します。[列のカスタマイズ] をクリックして、表示する列を選択します。
SQL でのクエリ
hologres.hg_query_log テーブルを直接クエリすることで、最大限の柔軟性が得られます。すぐに使用できる SQL の例については、「Diagnose queries」をご参照ください。
SQL フィンガープリント
V2.2 以降、hg_query_log の digest 列には、各クエリの SQL フィンガープリントが保存されます。SELECT、INSERT、DELETE、UPDATE 文では、Hologres が MD5 ハッシュをフィンガープリントとして計算します。
digest と query_id の使い分け:
同じタイプのクエリをグループ化して分析する場合は、
digestを使用します。たとえば、平均で最も CPU を消費するクエリパターンを特定できます。特定のクエリの実行を追跡する場合は、
query_idを使用します。たとえば、特定の失敗したクエリの詳細をすべて取得できます。
フィンガープリントの計算方法:
フィンガープリントは、SELECT、INSERT、DELETE、UPDATE 文に対してのみ収集されます。
空白 (スペース、改行、タブ) は無視されます。
定数値は無視されます。
SELECT * FROM t WHERE a > 1とSELECT * FROM t WHERE a > 2は同じフィンガープリントになります。配列の要素数は無視されます。
WHERE a IN (1, 2)とWHERE a IN (3, 4, 5)は同じフィンガープリントになります。定数データを含む INSERT 文の場合、フィンガープリントは挿入される行数の影響を受けません。
大文字と小文字は Hologres のクエリルールに従います。
フィンガープリントにはデータベース名と完全修飾スキーマが含まれます。そのため、
SELECT * FROM tとSELECT * FROM public.tが同じフィンガープリントになるのは、tがpublicスキーマにあり、かつ両方のクエリが同じテーブルを参照している場合のみです。
クエリの診断
以下の SQL の例は、最も一般的な診断シナリオを対象としています。すべてのクエリは hologres.hg_query_log を対象とします。
ログ内のスロークエリをカウント (デフォルト:先月):
SELECT count(*) FROM hologres.hg_query_log;出力例 — 先月 44 件のスロークエリ:
count
-------
44
(1 row)ユーザーごとのスロークエリ数をカウント:
SELECT usename AS "User",
count(1) AS "Query count"
FROM hologres.hg_query_log
GROUP BY usename
ORDER BY count(1) DESC;出力例:
User | Query count
---------------------+-------------
1111111111111111 | 27
2222222222222222 | 11
3333333333333333 | 4
4444444444444444 | 2
(4 rows)ID で特定のクエリを検索:
SELECT * FROM hologres.hg_query_log WHERE query_id = '13001450118416xxxx';返されるフィールドの説明については、「hg_query_log テーブル」をご参照ください。
過去 10 分間のリソース集約型クエリを検索:
対象の時間範囲に合わせて間隔を調整してください。
SELECT status AS "Status",
duration AS "Duration (ms)",
query_start AS "Start time",
(read_bytes / 1048576)::text || ' MB' AS "Data read",
(memory_bytes / 1048576)::text || ' MB' AS "Memory",
(shuffle_bytes / 1048576)::text || ' MB' AS "Shuffle",
(cpu_time_ms / 1000)::text || ' s' AS "CPU time",
physical_reads AS "Disk reads",
query_id AS "Query 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;出力例:
Status | Duration (ms) | Start time | Data read | Memory | Shuffle | CPU time | Disk reads | Query ID | query
---------+---------------+------------------------+-----------+--------+---------+----------+------------+--------------------+--------------------------------
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)シナリオ:インスタンスバージョンのアップグレード後に CPU またはメモリ使用率が高い場合の診断
このクエリは、Hologres インスタンスバージョンのアップグレード後に CPU またはメモリ使用率が急上昇した場合に特に役立ちます。リソース消費が高い原因となっているクエリを特定するには:
CPU またはメモリの使用量が異常に高かった期間が含まれるように、
WHERE句の時間範囲を調整します。 たとえば、interval '10 min'を、スパイクが発生した時間ウィンドウに一致する範囲に置き換えます。CPU 負荷の高いクエリを検索するには
ORDER BY cpu_time_ms DESCを、メモリを大量に消費するクエリを検索するにはORDER BY memory_bytes DESCを追加します。結果の
query_id、usename、およびquery列を確認して特定のクエリとその所有者を特定し、それらのクエリを適宜分析および最適化します。
ステージごとの所要時間の内訳:
これにより、どのステージ (optimization_cost、start_query_cost、または get_next_cost) が遅延の大部分を占めているかを特定できます。各ステージの詳細については、hg_query_log テーブルセクションの期間の内訳テーブルをご参照ください。
SELECT status AS "Status",
duration AS "Duration (ms)",
optimization_cost AS "Optimization cost (ms)",
start_query_cost AS "Startup cost (ms)",
get_next_cost AS "Execution cost (ms)",
duration - optimization_cost - start_query_cost - get_next_cost AS "Other cost (ms)",
query_id AS "Query 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;出力例:
Status | Duration (ms) | Optimization cost (ms) | Startup cost (ms) | Execution cost (ms) | Other cost (ms) | Query ID | query
---------+---------------+------------------------+-------------------+---------------------+-----------------+--------------------+--------------------------------
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)1 時間あたりのクエリ量とデータ読み取り量を表示 (過去 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;昨日の同じ時間帯のトラフィックと比較:
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;時間範囲内で最初に失敗したクエリを検索:
SELECT status AS "Status",
regexp_replace(message, '\n', ' ')::char(150) AS "Error message",
duration AS "Duration (ms)",
query_start AS "Start time",
query_id AS "Query ID",
query::char(100) AS "Query"
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;出力例:
Status | Error message | Duration (ms) | Start time | Query ID | Query
--------+--------------------------------------------------------------+---------------+------------------------+--------------------+-------
FAILED | Query:[1070285448673xxxx] code: kActorInvokeError msg: "..." | 1460 | 2021-03-25 17:28:54+08 | 1070285448673xxxx | S...
FAILED | Query:[1016285560553xxxx] code: kActorInvokeError msg: "..." | 131 | 2021-03-25 17:28:55+08 | 1016285560553xxxx | S...
(2 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)昨日の新しいクエリパターンを検索 (タイプ別):
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;出力例:
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;昨日の新しいクエリパターンを検索 (時間別):
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;出力例 — 昨日の 21:00 に 8 件の INSERT パターン、11:00 と 13:00 にそれぞれ 1 件の SELECT パターン:
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 のクエリパターンを検索 (過去 1 日):
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 のクエリパターンを検索 (過去 1 週間):
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;設定パラメータ
これらの GUC パラメータを使用して、ログに記録する内容や取得する詳細レベルを制御します。
log_min_duration_statement
ログに記録するクエリの最小実行時間を制御します。
デフォルト: 100 ms (V2.2.7 以降。それ以前のバージョンではデフォルトは 1,000 ms) 。
最小値: 100 ms 。
-1に設定すると、スロークエリのロギングが完全に無効になります。データベースレベルでこれを変更できるのはスーパーユーザーのみです。一般ユーザーはセッションレベルで変更できます。
変更は新しいクエリにのみ適用されます。
-- データベースレベル (スーパーユーザーのみ)
ALTER DATABASE dbname SET log_min_duration_statement = '250ms';
-- セッションレベル
SET log_min_duration_statement = '250ms';log_min_duration_query_stats
クエリの実行統計をキャプチャするかどうかを制御します。
デフォルト: 実行時間が 10 秒を超えるクエリの統計を記録します。
-1に設定すると、統計の収集が無効になります。統計は大量のストレージを使用します。この値を下げるのは、対象を絞ったトラブルシューティングの場合のみとし、終了後は元に戻してください。
変更は新しいクエリにのみ適用されます。
-- データベースレベル (スーパーユーザーのみ)
ALTER DATABASE dbname SET log_min_duration_query_stats = '20s';
-- セッションレベル
SET log_min_duration_query_stats = '20s';log_min_duration_query_plan
クエリの実行計画をキャプチャするかどうかを制御します。
デフォルト: 実行時間が 10 秒を超えるクエリのプランを記録します。
-1に設定すると、プランのキャプチャが無効になります。アドホックなトラブルシューティングには、
EXPLAINを使用してください。ログに記録せずに、プランを即座に返します。変更は新しいクエリにのみ適用されます。
-- データベースレベル (スーパーユーザーのみ)
ALTER DATABASE dbname SET log_min_duration_query_plan = '10s';
-- セッションレベル
SET log_min_duration_query_plan = '10s';ログ保持期間の変更
V3.0.27 以降では、データベースレベルでスロークエリログの保持期間を変更できます。
ALTER DATABASE <db_name> SET hg_query_log_retention_time_sec = 2592000;| 項目 | 詳細 |
|---|---|
| 単位 | 秒 |
| 範囲 | 3〜30 日 (259,200〜2,592,000 秒) |
| スコープ | 新規ログのみ (既存のログは元の保持期間を維持します) |
| 適用対象 | 新規接続のみ |
| クリーンアップ | 期限切れのログは、非同期ではなく即時に削除されます |
スロークエリログのエクスポート
hg_query_log から Hologres の内部テーブル、MaxCompute の外部テーブル、または OSS にデータをエクスポートし、長期的な保存や分析に利用します。
エクスポート前の注意点:
INSERT INTO ... SELECT ... FROM hologres.hg_query_logコマンドを実行するアカウントは、hg_query_logへのアクセス権を持つ必要があります。インスタンス全体をエクスポートするには、スーパーユーザーまたはpg_read_all_statsの権限が必要です。そうでない場合、エクスポートされたデータは不完全になります。query_startはインデックス列です。パフォーマンスを向上させ、リソース使用量を削減するために、常に WHERE 句に含めてください。WHERE 句で
query_startに関数を適用しないでください。これにより、インデックスが使用されなくなります。-- 正解例:query_start に直接範囲条件を使用します WHERE query_start >= '2022-08-03' AND query_start < '2022-08-04' -- 不正解例:query_start を関数でラップすると、インデックスがバイパスされます WHERE to_char(query_start, 'yyyymmdd') = '20220101'
Hologres の内部テーブルへのエクスポート
-- ステップ 1:ターゲットテーブルの作成
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_bytes bigint,
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[]
);
-- ステップ 2:特定の日付のログをエクスポート
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';MaxCompute の外部テーブルへのエクスポート
MaxCompute で、データ格納用のパーティションテーブルを作成します:
CREATE TABLE IF NOT EXISTS mc_holo_query_log ( username STRING COMMENT 'クエリのユーザー名', status STRING COMMENT 'クエリの最終ステータス:success または failed', 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 'SQL ステートメントの書き込み先テーブル', table_read ARRAY<STRING> COMMENT 'SQL ステートメントの読み取り元テーブル', 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 'クエリに関するその他の拡張情報 (ARRAY 形式)', query_start STRING COMMENT 'クエリの開始時間', query_date STRING COMMENT 'クエリの開始日' ) COMMENT 'Hologres インスタンスのクエリログ' 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 V1.1 で、返却行数と読み取り行数が表示されません。
これは、V1.1 の一部のバージョンでは、スロークエリログの収集が不完全なために発生します。V1.1.36~V1.1.49 では、次の GUC パラメーターを有効にして、完全な実行統計を収集してください。
-- データベースレベル (推奨:データベースごとに 1 回設定)
ALTER DATABASE <db_name> SET hg_experimental_force_sync_collect_execution_statistics = ON;
-- セッションレベル
SET hg_experimental_force_sync_collect_execution_statistics = ON;<db_name> をお使いのデータベース名に置き換えてください。
インスタンスのバージョンが V1.1.36 より前の場合は、「Common upgrade preparation errors」を参照するか、Hologres サポートにお問い合わせください。詳細については、「How do I get more online support?」をご参照ください。
この動作は、V1.1.49 以降ではデフォルトで解消されています。
スロークエリログの期間にはフェッチ時間が含まれますか。
いいえ。Hologres のスロークエリログの duration フィールドは、サーバー側の実行時間のみを測定します。これは、プラン生成 (optimization_cost)、起動 (start_query_cost)、計算 (get_next_cost) で構成されます。クライアントが結果データをフェッチする時間 (フェッチフェーズ) は含まれません。
Quick BI などの BI ツールからのクエリが、同じ SQL ステートメントを HoloWeb またはコマンドラインで実行した場合よりも大幅に時間がかかる場合、一般的な原因は次のとおりです。
BI ツールが複数のクエリを同時に送信するため、並列性が高くなり全体の応答時間が増加します。
get_next_costフィールドには、結果データをサーバーからクライアントに送信するためのネットワーク転送時間が含まれます。get_next_costの値が大きい場合、サーバー側の計算が遅いのではなく、クライアント側のデータ取得レイテンシーを反映している可能性があります。
サーバー側とクライアント側の遅延を切り分けるには、EXPLAIN ANALYZE を使用してクエリを実行し、get_next_cost フィールドを確認してください。get_next_cost が高く、optimization_cost と start_query_cost が低い場合、通常はクエリ実行ではなくデータ転送に時間が費やされていることを示します。
次のステップ
インスタンス内のアクティブなクエリを監視および管理するには、「Manage queries」をご参照ください。