DataBase  /  MySQL  /  レポート取得ガイド

Slow Query Log による取得とセクション定義

MySQL Slow Query Log は、指定した実行時間閾値を超えたクエリを自動記録する機能です。 Oracle AWR の SQL Statistics セクション(重い SQL の特定)に最も直接的に対応する情報源で、 実行時間・スキャン行数・インデックス使用状況などを記録します。

1. Slow Query Log の有効化と設定

動的有効化(再起動不要)

SQL — 動的有効化
-- 現在の設定を確認
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 による永続化

ini — /etc/mysql/my.cnf または /etc/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(全クエリ記録)も有効ですが、 ログが大量に生成されるため本番環境では注意が必要です。

2. ログエントリの構造とセクション定義

Slow Query Log の1エントリは以下の構造を持ちます。

Log — Slow Query Log エントリ例
# 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. 各フィールドの詳細定義

ヘッダー行

フィールド説明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. 追加記録項目

SQL — 追加情報を有効化(MySQL 8.0+)
-- 実行計画情報もログに記録(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. ログローテーションと管理

bash — ログローテーション
# ログファイルをローテーション(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 で直接集計できます。

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 モードの両方を有効にすることも可能です(log_output = 'FILE,TABLE')。