DBAtlas · データベース運用アトラス

長時間実行クエリ / ジョブ

症状

単一のクエリ/ジョブが何時間も終わらずに実行されている。リソースを消費するか、他に影響を与えている。

1. クエリとその実行時間を把握する

どのクエリが、どれだけの時間実行されているか。どのユーザー/アプリケーションか。

Oracle

SELECT sid, serial#, sql_id, last_call_et/60 running_min, username FROM v$session WHERE status='ACTIVE' AND type='USER' ORDER BY last_call_et DESC;

PostgreSQL

SELECT pid, now()-query_start dur, usename, query FROM pg_stat_activity WHERE state='active' ORDER BY query_start;

MySQL

SELECT id, user, time, state, info FROM information_schema.processlist WHERE command='Query' ORDER BY time DESC;

SQL Server

SELECT session_id, total_elapsed_time/1000 sec, status, command FROM sys.dm_exec_requests WHERE session_id IN (SELECT session_id FROM sys.dm_exec_sessions WHERE is_user_process = 1) ORDER BY total_elapsed_time DESC;

MongoDB

db.currentOp({ active: true, secs_running: { $gt: 60 } })

2. 進行しているか、停止しているか

本当に実行中か、それともロックを待っているか。進捗指標を確認する (Oracle v$session_longops、PG pg_stat_progress_* ビュー)。待機している場合は、ブロッキングのプレイブックに切り替える。

Oracle

SELECT sid, opname, sofar, totalwork, ROUND(sofar/NULLIF(totalwork,0)*100,1) pct, time_remaining FROM v$session_longops WHERE sofar<totalwork;

PostgreSQL

SELECT * FROM pg_stat_progress_create_index;  -- or pg_stat_progress_vacuum / _cluster / _analyze

3. 判断: 待つか、キャンセルするか

進行中でまもなく終わるなら待つ (キャンセルによるロールバックのコストでさらに時間がかかることがある)。停止している、誤って実行されている、または本番に影響している場合は終了する。キャンセルの前にロールバック時間を考慮する。

4. 必要に応じて終了する

まずクエリのみのキャンセル (セッションは維持) を優先し、効かなければセッションを強制終了する。

Oracle

ALTER SYSTEM CANCEL SQL 'sid,serial#';  -- 18c+; otherwise KILL SESSION

PostgreSQL

SELECT pg_cancel_backend(pid);  -- otherwise pg_terminate_backend(pid)

MySQL

KILL QUERY <id>;

SQL Server

KILL <session_id>;

MongoDB

db.killOp(<opid>)

5. 恒久的に修正する

クエリを最適化し (インデックス、計画、ページネーション/バッチ化)、重いジョブはオフピーク時間に移し、必要なら分割して実行する。定期的なレポートには、マテリアライズドビュー / 読み取りレプリカを検討する。

DBAtlas で開く →