DataBase / MySQL / レポート取得ガイド
Slow Query Log による取得とセクション定義
MySQL Slow Query Log は、指定した実行時間閾値を超えたクエリを自動記録する機能です。 Oracle AWR の SQL Statistics セクション(重い SQL の特定)に最も直接的に対応する情報源で、 実行時間・スキャン行数・インデックス使用状況などを記録します。
1. Slow Query Log の有効化と設定
動的有効化(再起動不要)
-- 現在の設定を確認
SHOW GLOBAL VARIABLES LIKE 'slow%';
SHOW GLOBAL VARIABLES LIKE 'long_query_time';
SHOW GLOBAL VARIABLES LIKE 'log_output';
-- 有効化(動的、再起動不要)
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1; -- 1秒以上を記録
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SET GLOBAL log_queries_not_using_indexes = 'ON'; -- インデックス未使用も記録
SET GLOBAL log_throttle_queries_not_using_indexes = 10; -- 同クエリの記録上限(分当たり)
my.cnf による永続化
[mysqld]
slow_query_log = ON
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 1
log_queries_not_using_indexes = ON
log_throttle_queries_not_using_indexes = 10
min_examined_row_limit = 100 # 100行以上スキャンしたクエリのみ
log_output = FILE # FILE / TABLE / NONE
💡 long_query_time の目安
初期チューニングでは 1〜2 秒から始め、ログ量に応じて調整します。 すべての遅いクエリを網羅したい場合は 0(全クエリ記録)も有効ですが、 ログが大量に生成されるため本番環境では注意が必要です。
初期チューニングでは 1〜2 秒から始め、ログ量に応じて調整します。 すべての遅いクエリを網羅したい場合は 0(全クエリ記録)も有効ですが、 ログが大量に生成されるため本番環境では注意が必要です。
2. ログエントリの構造とセクション定義
Slow Query Log の1エントリは以下の構造を持ちます。
# Time: 2026-05-29T14:32:01.123456Z
# User@Host: appuser[appuser] @ web01 [192.168.1.10] Id: 42
# Query_time: 3.456789 Lock_time: 0.000123 Rows_sent: 1 Rows_examined: 850432
# Rows_affected: 0 Bytes_sent: 245
# Thread_id: 42 Schema: mydb QC_hit: No
# Full_scan: Yes Full_join: No Tmp_table: No Tmp_table_on_disk: No
# Filesort: Yes Filesort_on_disk: No Merge_passes: 0
SET timestamp=1748526721;
SELECT u.user_id, u.name, COUNT(o.order_id) AS order_count
FROM users u
LEFT JOIN orders o ON u.user_id = o.user_id
WHERE u.created_at >= '2025-01-01'
GROUP BY u.user_id
ORDER BY order_count DESC
LIMIT 100;
3. 各フィールドの詳細定義
セクション定義: Slow Query Log フィールド
ヘッダー行
| フィールド | 説明 | Oracle AWR 対応 |
|---|---|---|
| # Time | クエリが完了した日時(UTC)。 | — |
| User@Host | 実行ユーザー名とクライアントホスト名・IP アドレス。 | Parsing User |
| Id | 接続スレッド ID。SHOW PROCESSLIST の Id と対応する。 |
— |
統計行(# Query_time ...)
| フィールド | 説明 | Oracle AWR 対応 |
|---|---|---|
| Query_time | クエリの合計実行時間(秒・小数点以下6桁)。 ロック待ち時間を含む。最重要指標。 | Elapsed Time per Exec |
| Lock_time | テーブルロック取得待ちの時間(秒)。 InnoDB 行ロック待ちは含まれず、MDL(メタデータロック)や MyISAM テーブルロックが対象。 | —(Lock Wait 相当) |
| Rows_sent | クライアントに返却した行数。 | Rows Processed |
| Rows_examined |
クエリがスキャンした行数。Rows_sent と大きく乖離している場合、
非効率なアクセスパス(フルスキャン・不適切なインデックス)の可能性がある。
|
Buffer Gets / Consistent Gets 相当 |
| Rows_affected | INSERT/UPDATE/DELETE で変更した行数。 | — |
| Bytes_sent | クライアントに送信したバイト数。 | — |
診断フラグ行(Percona Server / MariaDB 拡張)
| フィールド | 値 | 説明 |
|---|---|---|
| Full_scan | Yes / No | フルテーブルスキャンが発生した場合 Yes。インデックス追加の優先指標。 |
| Full_join | Yes / No | インデックスを使用しない JOIN が発生した場合 Yes。 |
| Tmp_table | Yes / No | 内部一時テーブル(メモリ上)が使用された場合 Yes。 |
| Tmp_table_on_disk | Yes / No | 一時テーブルがディスクに溢れた場合 Yes。tmp_table_size の拡大を検討。 |
| Filesort | Yes / No | ORDER BY をインデックスでカバーできずファイルソートが発生した場合 Yes。 |
| Filesort_on_disk | Yes / No | ファイルソートがディスクに溢れた場合 Yes。sort_buffer_size の拡大を検討。 |
4. 追加記録項目
-- 実行計画情報もログに記録(MySQL 8.0.18+)
SET GLOBAL log_slow_extra = ON;
-- 有効化後に記録される追加フィールド例
-- Cpu_user_time / Cpu_kernel_time : CPU 使用時間
-- Bytes_received / Bytes_sent : ネットワーク転送量
-- Tmp_tables / Tmp_disk_tables : 一時テーブル詳細
5. ログローテーションと管理
# ログファイルをローテーション(mysqladmin)
mysqladmin -u root -p flush-logs
# または MySQL コマンドで
# FLUSH SLOW LOGS;
# logrotate 設定例(/etc/logrotate.d/mysql)
/var/log/mysql/mysql-slow.log {
daily
rotate 7
missingok
compress
delaycompress
sharedscripts
postrotate
/usr/bin/mysqladmin -u root -p'password' flush-logs 2>/dev/null
endscript
}
⚠️ ログファイルのサイズ管理
long_query_time = 0(全クエリ記録)や高負荷環境では、
ログファイルが急速に増大します。ディスク使用量を定期的に監視し、
ローテーションを適切に設定してください。
6. テーブル出力モード
log_output = TABLE に設定すると、Slow Query Log が
mysql.slow_log テーブルに書き込まれ、SQL で直接集計できます。
SET GLOBAL log_output = 'TABLE';
SET GLOBAL slow_query_log = 'ON';
-- slow_log テーブルの構造確認
DESCRIBE mysql.slow_log;
-- 直近1時間の遅いクエリを実行時間順に表示
SELECT
start_time,
user_host,
query_time,
lock_time,
rows_sent,
rows_examined,
db,
SUBSTR(sql_text, 1, 200) AS sql_snippet
FROM mysql.slow_log
WHERE start_time >= NOW() - INTERVAL 1 HOUR
ORDER BY query_time DESC
LIMIT 50;
-- DB別の遅いクエリ件数・平均実行時間
SELECT
db,
COUNT(*) AS slow_count,
AVG(TIME_TO_SEC(query_time)) AS avg_sec,
MAX(TIME_TO_SEC(query_time)) AS max_sec,
SUM(rows_examined) AS total_rows_examined
FROM mysql.slow_log
GROUP BY db
ORDER BY slow_count DESC;
✅ テーブルモードの利点と欠点
テーブルモードは SQL で柔軟に集計・分析できますが、ログ自体が DB に保存されるため、 DB 障害時にログが失われるリスクがあります。 重要な環境では FILE モードと TABLE モードの両方を有効にすることも可能です(
テーブルモードは SQL で柔軟に集計・分析できますが、ログ自体が DB に保存されるため、 DB 障害時にログが失われるリスクがあります。 重要な環境では FILE モードと TABLE モードの両方を有効にすることも可能です(
log_output = 'FILE,TABLE')。