MySQL の innodb_buffer_pool_size を適切に設定する

InnoDB のパフォーマンスに最も影響を与える設定が innodb_buffer_pool_size です。この値を適切に設定することで、ディスク I/O を大幅に削減できます。

バッファプールとは

バッファプールは、InnoDB がテーブルやインデックスのデータをキャッシュするメモリ領域です。データがバッファプール内にあれば、ディスクアクセスなしで読み取れます。

データがバッファプール内

メモリから読み取り(マイクロ秒単位)

データがバッファプール外

ディスクから読み取り(ミリ秒単位)

キャッシュヒット率が高いほど、クエリは高速に実行されます。

現在の設定を確認する

SHOW VARIABLES LIKE 'innodb_buffer_pool_size';

デフォルトは 128MB ですが、本番環境ではこれでは小さすぎることがほとんどです。

適切なサイズの決め方

一般的な指針は、専用データベースサーバーの場合、物理メモリの 70〜80% をバッファプールに割り当てるというものです。

専用 DB サーバー(16GB RAM)

innodb_buffer_pool_size = 11G〜12G

他アプリと共存(8GB RAM)

innodb_buffer_pool_size = 4G〜5G

開発環境(4GB RAM)

innodb_buffer_pool_size = 1G〜2G

OS やその他のプロセスにもメモリが必要なので、全量を割り当てないように注意してください。

設定方法

my.cnf(または my.ini)に以下を追加します。

[mysqld]
innodb_buffer_pool_size = 12G

MySQL 5.7.5 以降では、動的に変更することも可能です。

SET GLOBAL innodb_buffer_pool_size = 12884901888;  -- 12GB in bytes

キャッシュヒット率を確認する

設定が適切かどうかは、キャッシュヒット率で判断できます。

SHOW STATUS LIKE 'Innodb_buffer_pool_read%';

以下の計算式でヒット率を算出します。

99% 以上非常に良好
95〜99%良好
90〜95%改善の余地あり
90% 未満バッファプール不足の可能性

innodb_buffer_pool_instances

MySQL 5.5 以降では、バッファプールを複数のインスタンスに分割できます。これにより、並行アクセス時のロック競合が減少します。

[mysqld]
innodb_buffer_pool_size = 12G
innodb_buffer_pool_instances = 8

バッファプールが 1GB 以上の場合、インスタンス数を増やすことが推奨されています。各インスタンスが 1GB 以上になるように設定するのが目安です。

ウォームアップの問題

MySQL を再起動すると、バッファプールは空の状態からスタートします。データがキャッシュされるまで、しばらくパフォーマンスが低下します。

MySQL 5.6 以降では、シャットダウン時にバッファプールの内容を保存し、起動時に復元できます。

[mysqld]
innodb_buffer_pool_dump_at_shutdown = ON
innodb_buffer_pool_load_at_startup = ON

これにより、再起動後もすぐに高いキャッシュヒット率を維持できます。

監視すべき指標

バッファプールの状態を継続的に監視しましょう。

SELECT 
    (1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)) * 100 AS hit_ratio,
    Innodb_buffer_pool_pages_free,
    Innodb_buffer_pool_pages_total
FROM (
    SELECT 
        MAX(IF(Variable_name = 'Innodb_buffer_pool_reads', Variable_value, 0)) AS Innodb_buffer_pool_reads,
        MAX(IF(Variable_name = 'Innodb_buffer_pool_read_requests', Variable_value, 0)) AS Innodb_buffer_pool_read_requests,
        MAX(IF(Variable_name = 'Innodb_buffer_pool_pages_free', Variable_value, 0)) AS Innodb_buffer_pool_pages_free,
        MAX(IF(Variable_name = 'Innodb_buffer_pool_pages_total', Variable_value, 0)) AS Innodb_buffer_pool_pages_total
    FROM performance_schema.global_status
) t;

pages_free が常に 0 に近い状態が続くなら、バッファプールの増量を検討してください。

まとめ

専用サーバーなら物理メモリの 70〜80%
キャッシュヒット率 99% 以上を目標
1GB 以上なら複数インスタンスに分割
ウォームアップ設定を有効化
継続的にヒット率を監視

バッファプールの適切な設定は、チューニングの中で最もコストパフォーマンスが高い施策の一つです。まずはここから見直してみてください。