Aurora MySQLで特定のクエリが遅くなったときの確認手順
公開日 2026-08-13 · 更新日 2026-08-13 · 最終検証日 2026-08-13
結論
Aurora MySQLで特定のクエリが遅い場合は、(1) スロークエリログ(`slow_query_log` と `long_query_time`)で遅いSQLを特定し、(2) `SHOW FULL PROCESSLIST` で実行中のセッションと待ち状態を確認し、(3) `EXPLAIN` で実行計画を確認する、の順で切り分けます。`performance_schema` が有効ならダイジェスト集計とPerformance Insightsで待機事象まで追えますが、無効でもこの3つとCloudWatchメトリクスで大半は切り分けられます。
この文書の適用条件
| 対象製品 | Aurora MySQL(MySQL互換エディション) |
|---|---|
| 確認バージョン | Aurora MySQL 2.x(MySQL 5.7互換)/ 3.x(MySQL 8.0互換)。`EXPLAIN ANALYZE` はMySQL 8.0で追加されたため 3.x のみ |
| 適用環境 | Amazon Aurora(AWS) |
| 必要権限 | 参照系は対象スキーマへの `SELECT`。他ユーザーのセッションやトランザクションを見るには `PROCESS` 権限。パラメータ変更にはIAMの `rds:ModifyDBParameterGroup` とマスターユーザー相当の権限 |
| 実行影響 | 参照系は影響なし。`EXPLAIN ANALYZE` は対象クエリを実際に実行する。パラメータ変更は設定変更にあたる |
| 再起動 | 参照系は不要。`performance_schema` の有効化はインスタンス再起動が必要 |
| 最終検証日 | 2026-08-13 |
そのまま実行できるコマンド
- 対象
- Aurora MySQL 2.x / 3.x
- 権限
- 接続権限(グローバル変数の参照)
- 変更作業
- なし(参照のみ)
- Production実行
- 可能
-- 対象: Aurora MySQL 2.x / 3.x
-- 権限: 接続権限(グローバル変数の参照のみ)
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SHOW GLOBAL VARIABLES WHERE Variable_name IN (
'slow_query_log',
'long_query_time',
'log_output',
'log_queries_not_using_indexes',
'min_examined_row_limit',
'performance_schema'
);`performance_schema` が `OFF` の場合、この記事のダイジェスト集計は使えません。その場合はスロークエリログとPROCESSLIST、`information_schema.INNODB_TRX`、CloudWatchメトリクスで切り分けます。
- 対象
- Aurora MySQL 2.x / 3.x
- 権限
- 自分以外のセッションを見るには `PROCESS` 権限
- 変更作業
- なし(参照のみ)
- Production実行
- 可能
-- 対象: Aurora MySQL 2.x / 3.x
-- 権限: 自分以外のセッションを見るには PROCESS 権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
ID,
USER,
HOST,
DB,
COMMAND,
TIME AS elapsed_sec,
STATE,
LEFT(INFO, 200) AS query_head
FROM information_schema.PROCESSLIST
WHERE COMMAND <> 'Sleep'
ORDER BY TIME DESC;`SHOW FULL PROCESSLIST` と同じ情報を並べ替え・絞り込みできる形です。MySQL 8.0互換(Aurora MySQL 3.x)では `performance_schema.processlist` も利用でき、こちらはグローバルなミューテックスを取らない実装のため、多数の接続がある環境で影響が小さくなります。
- 対象
- Aurora MySQL 2.x / 3.x
- 権限
- `PROCESS` 権限
- 変更作業
- なし(参照のみ)
- Production実行
- 可能
-- 対象: Aurora MySQL 2.x / 3.x
-- 権限: PROCESS 権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
trx_id,
trx_state,
trx_started,
TIMESTAMPDIFF(SECOND, trx_started, NOW()) AS open_sec,
trx_mysql_thread_id,
trx_rows_locked,
trx_rows_modified,
LEFT(trx_query, 200) AS current_query
FROM information_schema.INNODB_TRX
ORDER BY trx_started ASC;遅いのが特定のクエリではなくロック待ちである場合、ここに長時間 `RUNNING` のまま残っているトランザクションが見えます。`performance_schema` の有効・無効に関係なく参照できます。
- 対象
- Aurora MySQL 2.x / 3.x(`performance_schema = ON` が前提)
- 権限
- `performance_schema` への `SELECT`
- 変更作業
- なし(参照のみ)
- Production実行
- 可能
-- 対象: Aurora MySQL 2.x / 3.x(performance_schema = ON が前提)
-- 権限: performance_schema への SELECT
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
SCHEMA_NAME,
LEFT(DIGEST_TEXT, 200) AS digest_head,
COUNT_STAR AS exec_count,
ROUND(SUM_TIMER_WAIT / 1000000000000, 3) AS total_sec,
ROUND(AVG_TIMER_WAIT / 1000000000000, 6) AS avg_sec,
SUM_ROWS_EXAMINED AS rows_examined,
SUM_ROWS_SENT AS rows_sent,
SUM_NO_INDEX_USED AS no_index_used,
SUM_CREATED_TMP_DISK_TABLES AS tmp_disk_tables,
FIRST_SEEN,
LAST_SEEN
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 20;`*_TIMER_WAIT` の単位はピコ秒なので、10^12 で割って秒に直しています。集計はインスタンス起動以降の累積で、再起動やフェイルオーバーでリセットされます。
- 対象
- `EXPLAIN` は 2.x / 3.x、`EXPLAIN ANALYZE` は 3.x(MySQL 8.0互換)のみ
- 権限
- 対象テーブルへの `SELECT`
- 変更作業
- なし。ただし `EXPLAIN ANALYZE` は対象クエリを実際に実行する
- Production実行
- `EXPLAIN` は可能。`EXPLAIN ANALYZE` は実行負荷を許容できる場合のみ
-- 対象: EXPLAIN は Aurora MySQL 2.x / 3.x、EXPLAIN ANALYZE は 3.x(MySQL 8.0互換)のみ
-- 権限: 対象テーブルへの SELECT
-- 変更作業: なし(EXPLAIN ANALYZE はクエリを実際に実行する点に注意)
-- Production 実行: EXPLAIN は可能/EXPLAIN ANALYZE は実行負荷を許容できる場合のみ
-- 1) 実行計画だけを見る(クエリは実行されない)
EXPLAIN
SELECT id, name, updated_at
FROM SampleDB.sample_table
WHERE status = 'active'
AND updated_at >= '2026-08-01'
ORDER BY updated_at DESC
LIMIT 100;
-- 2) 実測値つきの実行計画(Aurora MySQL 3.x のみ。クエリを実際に実行する)
EXPLAIN ANALYZE
SELECT id, name, updated_at
FROM SampleDB.sample_table
WHERE status = 'active'
AND updated_at >= '2026-08-01'
ORDER BY updated_at DESC
LIMIT 100;`EXPLAIN ANALYZE` は推定行数ではなく実測行数と実測時間を返すため、推定のずれを直接確認できます。ただしクエリを実際に実行するので、更新系や重い集計に対しては使わないでください。`EXPLAIN FORMAT=JSON` はコスト値まで含めた詳細を返し、こちらは実行を伴いません。
- 対象
- Aurora MySQL 2.x / 3.x(DBパラメータグループとDBクラスターの設定)
- 権限
- IAM: `rds:ModifyDBParameterGroup`, `rds:ModifyDBCluster`
- 変更作業
- あり(パラメータ変更とログ出力設定の変更)
- Production実行
- 事前に変更管理を通したうえで実施。ログ量の増加を見込むこと
# 対象: Aurora MySQL 2.x / 3.x(DBパラメータグループとDBクラスター設定)
# 権限: IAM rds:ModifyDBParameterGroup, rds:ModifyDBCluster
# 変更作業: あり(パラメータ変更 + ログ出力先の変更)
# Production 実行: 変更管理を通したうえで実施。ログ量とストレージ増加を見込むこと
# 1) スロークエリログを有効化する(いずれも動的パラメータとして扱われる想定。
# 実際の反映方法は describe-db-parameters の ApplyType で確認すること)
aws rds modify-db-parameter-group \
--db-parameter-group-name example-aurora-mysql-params \
--parameters '[
{"ParameterName":"slow_query_log","ParameterValue":"1","ApplyMethod":"immediate"},
{"ParameterName":"long_query_time","ParameterValue":"1","ApplyMethod":"immediate"},
{"ParameterName":"log_output","ParameterValue":"FILE","ApplyMethod":"immediate"}
]'
# 2) クラスター単位でスロークエリログをCloudWatch Logsへ出力する
aws rds modify-db-cluster \
--db-cluster-identifier example-aurora-cluster \
--cloudwatch-logs-export-configuration '{"EnableLogTypes":["slowquery","error"]}' \
--apply-immediately
# 3) 反映後の値を確認する
aws rds describe-db-parameters \
--db-parameter-group-name example-aurora-mysql-params \
--query "Parameters[?ParameterName=='slow_query_log' || ParameterName=='long_query_time'].{Name:ParameterName,Value:ParameterValue,Apply:ApplyType,Status:ApplyMethod}" \
--output table`long_query_time` を小さくするほど記録されるクエリが増え、ログ量とCloudWatch Logsの料金が増えます。まず 1 秒程度から始め、必要に応じて下げてください。`log_output` を `TABLE` にすると `mysql.slow_log` テーブルからSQLで参照できますが、書き込みがテーブルへの挿入になるため負荷の性質が変わります。
- 対象
- Aurora MySQL 2.x / 3.x(DBパラメータグループ)
- 権限
- IAM: `rds:ModifyDBParameterGroup`, `rds:RebootDBInstance`
- 変更作業
- あり(静的パラメータの変更 + インスタンス再起動)
- Production実行
- 再起動を伴うため不可。メンテナンス時間帯に計画実行する
# 対象: Aurora MySQL 2.x / 3.x(DBパラメータグループ)
# 権限: IAM rds:ModifyDBParameterGroup, rds:RebootDBInstance
# 変更作業: あり(静的パラメータ変更 + インスタンス再起動)
# Production 実行: 不可(再起動を伴うためメンテナンス時間帯に計画実行)
# 1) performance_schema を有効化する(再起動時に反映)
aws rds modify-db-parameter-group \
--db-parameter-group-name example-aurora-mysql-params \
--parameters '[
{"ParameterName":"performance_schema","ParameterValue":"1","ApplyMethod":"pending-reboot"}
]'
# 2) 反映のためインスタンスを再起動する(接続断が発生する)
aws rds reboot-db-instance --db-instance-identifier example-aurora-instance`performance_schema` は再起動が必要なパラメータです。再起動は接続断とフェイルオーバー相当の影響を伴うため、必ず計画停止として扱ってください。Performance Insightsの一部の詳細情報も `performance_schema` に依存します。有効化によるメモリ消費の増加分は環境ごとに異なるため、事前に検証環境で計測してください。
結果の読み方
| 列 | 意味 | 確認するポイント |
|---|---|---|
| SCHEMA_NAME | ダイジェストが属するスキーマ | 対象アプリケーションのスキーマに絞って見る |
| digest_head | リテラルを正規化したSQL文の先頭 | 同じ形のSQLがまとめられている。全文は `DIGEST_TEXT` を直接参照する |
| exec_count | 実行回数(`COUNT_STAR`) | 1回が遅いのか、回数が多くて合計が大きいのかを区別する |
| total_sec | 累積実行時間(秒) | 上位から順に負荷の主因。まずここを見る |
| avg_sec | 1回あたりの平均実行時間(秒) | 合計は小さいが平均が大きいクエリは、実行タイミング次第で問題化する |
| rows_examined | 走査した行数の累計 | `rows_sent` に対して桁違いに大きい場合、インデックスが効いていない可能性が高い |
| rows_sent | 返した行数の累計 | `rows_examined` との比が効率の目安 |
| no_index_used | インデックスを使わなかった実行回数 | 0 でなければ `EXPLAIN` でアクセス方法を確認する |
| tmp_disk_tables | ディスク上の一時テーブルを作った回数 | 大きい場合はソート・グループ化の見直し対象 |
| FIRST_SEEN / LAST_SEEN | 最初・最後に観測された時刻 | 遅くなった時期と一致するかを確認する |
こういう状況で使います
- 昨日まで問題なかった同じクエリが、ある時点から急に遅くなった
- アプリケーション側でタイムアウトが増えたが、CPU使用率は高くない
- 特定の画面・バッチだけが遅く、他の処理は正常
- Performance Insightsを見ようとしたが、`performance_schema` が無効で詳細が出ない
- `SHOW PROCESSLIST` に同じクエリが長時間残っている
考えられる原因(可能性の高い順)
01
実行計画が変わり、インデックスが使われなくなった
データ量の増加や統計の更新によって、オプティマイザが別のアクセス方法を選ぶことがあります。`rows_examined` が `rows_sent` に対して極端に大きくなっていれば、この可能性が高いです。
02
ロック待ちで実行が進んでいない
クエリ自体は軽くても、他のトランザクションが行ロックを保持していると待たされます。`information_schema.INNODB_TRX` に長時間開いたトランザクションが残っていないか確認します。
03
データ量が増えて走査コストが上がった
同じ実行計画でも、対象行が増えれば所要時間は伸びます。この場合はインデックス設計や検索条件の見直しが必要で、パラメータ調整では解決しません。
04
ソート・一時テーブルがディスクに落ちている
`ORDER BY` や `GROUP BY` の対象が大きいと一時テーブルがディスク上に作られます。ダイジェスト集計の `SUM_CREATED_TMP_DISK_TABLES` で確認できます。
05
リーダーインスタンス側のレプリカ遅延やリソース競合
読み取りをリーダーエンドポイントに向けている場合、ライターとリーダーで負荷状況が異なります。どのインスタンスで遅いのかを先に切り分けてください。
確認手順
- 1
どのインスタンス・どの時間帯かを特定する
参照のみCloudWatchの `CPUUtilization`、`DatabaseConnections`、`ReadLatency` / `WriteLatency`、`Deadlocks` を確認し、事象の発生時間帯とインスタンスを絞り込みます。
- 2
スロークエリログの設定値を確認する
参照のみ上記の `SHOW GLOBAL VARIABLES` を実行し、そもそもログが取れているか、`long_query_time` が実態に合っているかを確認します。
- 3
実行中セッションを確認する
参照のみ`information_schema.PROCESSLIST` で、遅いクエリが実行中なのか待機中なのかを確認します。`STATE` 列が手がかりになります。
- 4
長時間トランザクションとロックを確認する
参照のみ`information_schema.INNODB_TRX` を参照します。`performance_schema` が無効でも実行できます。
- 5
ダイジェスト集計で上位を洗い出す
参照のみ`performance_schema` が有効なら `events_statements_summary_by_digest` を累積実行時間の降順で確認します。
- 6
対象SQLの実行計画を確認する
低`EXPLAIN` でアクセス方法・使用インデックス・推定行数を見ます。推定と実測の差を見たい場合のみ、負荷を許容できる範囲で `EXPLAIN ANALYZE`(Aurora MySQL 3.x)を使います。
対応方法
すぐに実施できる低リスクの対応
スロークエリログを有効化して対象SQLを確定させる
高推測で対策する前に、実際に遅いSQLをログで確定させます。`long_query_time` はまず1秒程度から始めます。
ロック保持元のセッションをアプリ側で終了させる
高長時間開いたトランザクションが原因なら、まずアプリケーション側の処理を止めます。DB側の `KILL` は最終手段で、実行中の更新がロールバックされます。
事前検討が必要な変更
検索条件に合うインデックスを追加する
高`EXPLAIN` の結果をもとに、絞り込みと並び替えの両方を満たす複合インデックスを検討します。追加はスキーマ変更にあたるため、検証環境での確認と実行時間帯の調整が必要です。
クエリを書き換えて走査行数を減らす
中関数を条件列に適用しない、必要な列だけを返す、ページングの方式を見直す、といった変更で `rows_examined` を減らします。
スロークエリログをCloudWatch Logsへ出力して継続的に確認する
高一時的に見るのではなく、ログを集約して推移を追える状態にします。ログ量に応じた料金が発生します。
再起動・サービス影響を伴う変更
performance_schema を有効化する
高再起動が必要な静的パラメータです。接続断を伴うため、計画停止として扱ってください。有効化後はダイジェスト集計とPerformance Insightsの詳細が使えるようになります。
インスタンスクラスを変更する
高CPUやメモリが恒常的に不足している場合の選択肢ですが、単一クエリの実行計画の問題は解決しません。先に原因の切り分けを終えてから判断してください。
!注意事項
- `EXPLAIN ANALYZE` は対象クエリを実際に実行します。更新系や重い集計に対しては使わないでください。
- `performance_schema` の有効化はインスタンス再起動を伴います。接続断が発生するため、無停止では実施できません。
- `long_query_time` を極端に小さくすると、ログ出力自体が負荷とストレージ消費の原因になります。
- `KILL` は実行中トランザクションのロールバックを発生させ、ロールバックには元の処理と同等以上の時間がかかることがあります。安易に使わないでください。
- ダイジェスト集計はインスタンス起動以降の累積値です。フェイルオーバーや再起動の直後は母数が小さく、判断材料になりません。
- この記事は原因の切り分け手順であり、特定の設定値を適用すれば速くなることを保証するものではありません。
バージョン・環境による違い
これで解決しない場合に確認すること
アプリケーション側のタイムアウトと接続プール設定を確認する
DB側の実行時間が変わっていないのに遅く見える場合、接続待ちやプール枯渇が原因のことがあります。
ライターとリーダーのどちらで遅いかを分離する
同じSQLをライター・リーダーそれぞれで実行し、差が出るかを確認します。差があるならインスタンス個別の負荷要因を疑います。
CloudWatchの `ReadIOPS` / `WriteIOPS` とバッファプールのヒット状況を確認する
ストレージ側で待っているのか、CPUで待っているのかで対処が変わります。
スキーマ変更やデプロイの履歴と時刻を突き合わせる
遅くなった時刻の前後に、インデックス削除やアプリケーションのクエリ変更がなかったかを確認します。
同じ症状が複数のクエリに出ていないかを確認する
単一クエリの問題か、インスタンス全体の問題かで切り分け先が変わります。
この文書の根拠と限界
製品の公式ドキュメントに基づく説明
MySQLのスロークエリログ関連システム変数、`information_schema.PROCESSLIST` / `INNODB_TRX`、`performance_schema.events_statements_summary_by_digest`、`EXPLAIN` / `EXPLAIN ANALYZE` の公開仕様、およびAmazon RDS / Aurora のパラメータグループとログ出力の公開仕様に基づく一般的な確認手順です。特定環境の実測値は含みません。
よくある質問
Productionで実行できますか?
`SHOW GLOBAL VARIABLES`、`information_schema.PROCESSLIST`、`information_schema.INNODB_TRX`、ダイジェスト集計、`EXPLAIN` はいずれも参照専用で、本番環境でそのまま実行できます。`EXPLAIN ANALYZE` はクエリを実際に実行し、パラメータ変更は設定変更にあたるため、それぞれ影響を確認してから実施してください。
performance_schema が無効でも原因を調べられますか?
調べられます。スロークエリログで遅いSQLを特定し、`SHOW FULL PROCESSLIST` と `information_schema.INNODB_TRX` で実行中の状態とロックを確認し、`EXPLAIN` で実行計画を見る、という流れで大半は切り分けられます。有効化には再起動が必要なので、まず無効のままできる範囲を尽くしてください。
performance_schema を有効にするには再起動が必要ですか?
必要です。DBパラメータグループで `performance_schema` を 1 に変更し、対象インスタンスを再起動して反映します。再起動は接続断を伴うため、計画停止として扱ってください。
どの権限が必要ですか?
自分のセッションと対象テーブルの `EXPLAIN` だけなら対象スキーマへの `SELECT` で足ります。他ユーザーのセッションや `INNODB_TRX` を見るには `PROCESS` 権限が必要です。パラメータ変更にはIAM権限(`rds:ModifyDBParameterGroup` など)が必要です。
結果をどう判断しますか?
`rows_examined` が `rows_sent` に対して桁違いに大きければアクセス方法の問題、`INNODB_TRX` に長時間のトランザクションがあればロック待ち、どちらでもなくCPUやI/Oが張り付いていればリソース側、と切り分けます。ダイジェスト集計は「累積実行時間」で並べ、1本の遅さと回数の多さを区別してください。
EXPLAIN ANALYZE は本番で使ってよいですか?
対象が参照系で、実行してもよい負荷であることを確認したうえでのみ使ってください。`EXPLAIN ANALYZE` は推定ではなく実測を返す代わりに、クエリを最後まで実行します。判断がつかない場合は `EXPLAIN FORMAT=JSON` を使ってください。
この文書がカバーする質問
- Aurora MySQLでスロークエリログを有効化して確認したい
- performance_schema=OFF環境での性能分析をどう進めるか
- MySQLで実行中のクエリと待ち状態を確認したい
- EXPLAINの結果からインデックスが効いていないか判断したい
リスク表示の意味
- 参照のみデータと設定を変更しません。
- 低影響は限定的ですが、権限と負荷の確認が必要です。
- 中性能・ロック・コストに影響する可能性があります。
- 高障害・データ損失・復旧作業が発生する可能性があります。
- 専門家レビュー必須本番適用前に別途レビューが必須です。
GIIPの対応範囲
遅いクエリを1本特定するところまでは、この記事の手順で到達できます。実際の運用で難しいのは、遅くなった「その瞬間」の情報が残っていないことです。GIIPでは、スロークエリログとCloudWatchメトリクスを常時収集したうえで、閾値を超えた時点の実行中セッションとトランザクション状態をあわせて記録し、事後に再現待ちをしなくても原因調査を始められる状態を維持しています。日常の収集と一次切り分けはAIエージェントが行い、実行計画の変更やインデックス追加といった判断が必要な段階で人が引き継ぎます。
執筆・技術検証
GIIP プロダクション運用チーム
大規模Webサービス、SQL Server、Oracle、AWS、Azureの設計・移行・運用に約30年従事。x12largeクラスのAWS RDS for SQL Server環境12セット、約12万テーブルのOracle環境、約3TBのTiDBからAurora MySQLへの移行を経験。現在も複数のクラウドデータベースと約30のWebサービスを、AIエージェントと人間の専門家が継続的に監視・運用しています。
Aurora MySQLで監査ログを取得して確認する方法
Aurora MySQLのAdvanced Auditingをクラスターパラメータで有効化し、CloudWatch LogsまたはRDSのログファイルとして確認する手順です。記録対象の絞り込み方も整理します。
aurora-mysqlAurora MySQLでutf8mb3からutf8mb4へ移行するときに確認すること
utf8mb4への変換で最初に壊れるのはインデックスのキー長です。対象の洗い出しSQL、照合順序の選び方、変換時の影響と設定箇所をまとめます。
sql-serverSQL Serverでテーブルごとの統計情報更新日時を確認するSQL
sys.stats と STATS_DATE で、テーブル・統計ごとの最終更新日時と更新後の変更行数を一覧化する参照専用SQLです。
monitoringサーバーとデータベースを24時間監視するときに設定する項目
24時間監視を設計する際の監視対象・しきい値の考え方・エスカレーション体制・外形監視の必要性を、層ごとに整理したチェックリストです。
関連サービス
遅いクエリの原因調査を依頼する
同じ確認を複数の環境で継続する必要がある場合は、運用体制ごと相談できます。
遅いクエリの原因調査を依頼する