MySQL の Performance Schema 入門

Performance Schema は MySQL 5.5 で導入された、サーバー内部の詳細なパフォーマンスデータを収集する仕組みです。SHOW STATUS や SHOW PROCESSLIST より詳細な情報が得られ、パフォーマンス問題の根本原因を突き止めるのに役立ちます。

Performance Schema とは

Performance Schema は、MySQL サーバー内部のイベント(クエリ実行、ファイル I/O、ロック待ちなど)を計測し、専用のデータベース performance_schema に保存します。

USE performance_schema;
SHOW TABLES;

100 以上のテーブルがありますが、よく使うものは限られています。

有効化の確認

SHOW VARIABLES LIKE 'performance_schema';

デフォルトで ON になっています。OFF の場合は my.cnf で有効化します。

[mysqld]
performance_schema = ON

重要なテーブル

用途別に主要なテーブルを紹介します。

クエリ分析

events_statements_summary_by_digest - クエリのダイジェストごとの統計

待機イベント

events_waits_summary_global_by_event_name - 何を待っているかの統計

ファイル I/O

file_summary_by_instance - ファイルごとの I/O 統計

メモリ使用量

memory_summary_global_by_event_name - メモリ使用状況(MySQL 5.7以降)

遅いクエリを見つける

events_statements_summary_by_digest は、クエリパターンごとの実行統計を提供します。

SELECT 
    DIGEST_TEXT,
    COUNT_STAR AS exec_count,
    SUM_TIMER_WAIT / 1000000000000 AS total_time_sec,
    AVG_TIMER_WAIT / 1000000000000 AS avg_time_sec,
    SUM_ROWS_EXAMINED,
    SUM_ROWS_SENT
FROM performance_schema.events_statements_summary_by_digest
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;

このクエリで、合計実行時間が長いクエリパターンがわかります。時間はピコ秒で記録されているため、10^12 で割って秒に変換しています。

フルスキャンが多いクエリ

テーブルフルスキャンが多いクエリを見つけます。

SELECT 
    DIGEST_TEXT,
    COUNT_STAR,
    SUM_NO_INDEX_USED,
    SUM_NO_GOOD_INDEX_USED
FROM performance_schema.events_statements_summary_by_digest
WHERE SUM_NO_INDEX_USED > 0
ORDER BY SUM_NO_INDEX_USED DESC
LIMIT 10;

SUM_NO_INDEX_USED が大きいクエリは、インデックスが使われていない可能性があります。

待機イベントの分析

何を待っているかがわかると、ボトルネックが特定しやすくなります。

SELECT 
    EVENT_NAME,
    COUNT_STAR,
    SUM_TIMER_WAIT / 1000000000000 AS total_wait_sec
FROM performance_schema.events_waits_summary_global_by_event_name
WHERE COUNT_STAR > 0
ORDER BY SUM_TIMER_WAIT DESC
LIMIT 10;
イベント名のパターン意味
wait/io/file/*ファイル I/O 待ち
wait/synch/mutex/*Mutex 待ち
wait/synch/rwlock/*Read-Write ロック待ち
wait/lock/table/*テーブルロック待ち

ファイル I/O 待ちが多ければディスク性能の問題、Mutex 待ちが多ければ並行処理の競合が疑われます。

ファイル I/O の詳細

どのファイルへの I/O が多いか確認できます。

SELECT 
    FILE_NAME,
    COUNT_READ,
    COUNT_WRITE,
    SUM_TIMER_READ / 1000000000000 AS read_time_sec,
    SUM_TIMER_WRITE / 1000000000000 AS write_time_sec
FROM performance_schema.file_summary_by_instance
ORDER BY SUM_TIMER_READ + SUM_TIMER_WRITE DESC
LIMIT 10;

特定のテーブルファイルや redo ログへのアクセスが集中していないか確認できます。

メモリ使用状況(MySQL 5.7以降)

どのコンポーネントがメモリを消費しているか確認できます。

SELECT 
    EVENT_NAME,
    CURRENT_NUMBER_OF_BYTES_USED / 1024 / 1024 AS current_mb
FROM performance_schema.memory_summary_global_by_event_name
ORDER BY CURRENT_NUMBER_OF_BYTES_USED DESC
LIMIT 10;

計測対象の設定

デフォルトでは一部のイベントしか計測されません。詳細な分析が必要な場合は、setup テーブルで設定を変更します。

-- 現在の設定を確認
SELECT * FROM performance_schema.setup_instruments WHERE NAME LIKE '%statement%';

-- 特定のイベントを有効化
UPDATE performance_schema.setup_instruments 
SET ENABLED = 'YES', TIMED = 'YES' 
WHERE NAME LIKE 'wait/io/file/%';

ただし、計測対象を増やすとオーバーヘッドも増えます。必要なものだけを有効化しましょう。

統計のリセット

長期間運用していると統計が累積します。特定の期間の分析をしたい場合はリセットします。

-- 全テーブルの統計をリセット
CALL sys.ps_truncate_all_tables(FALSE);

-- 特定のテーブルだけリセット
TRUNCATE TABLE performance_schema.events_statements_summary_by_digest;

sys スキーマとの連携

Performance Schema のデータは生のままだと読みにくいため、次回紹介する sys スキーマと組み合わせて使うのが一般的です。sys スキーマは Performance Schema のデータを人間が読みやすい形式でビューとして提供します。

Performance Schema は MySQL の詳細な内部動作を可視化する強力なツールです。最初は複雑に感じますが、よく使うテーブルから始めて徐々に活用範囲を広げていきましょう。