MySQL InnoDB Buffer Pool の最適値はこう決める:メトリクスとベンチマークで検証する実践チューニング

目次

はじめに

MySQL の性能チューニングで重要な設定のひとつが InnoDB Buffer Pool です。
Buffer Pool は InnoDB がデータページやインデックスページをキャッシュする領域で、
OLTP ワークロードではディスク I/O を減らすための中心的な役割を担います。

一般的には「Buffer Pool サイズは RAM の 70%程度」と言われますが、
実際には Buffer Pool を必要以上に大きくすると性能が低下する場合があります。


Buffer Pool の最適値

Buffer Pool の値は固定比率ではなく、実際のワークロードで計測して決めることが最も確実です。

今回の検証では HammerDB(TPROC‑C)と Prometheus を使い、
Buffer Pool サイズを段階的に変えながら MySQL の性能を計測しました。
その結果、Buffer Pool の最適値は”意外な場所”にあることが分かりました。

検証環境と方法(HammerDB + Prometheus)

ハードウェア・ソフトウェア構成

検証環境は以下のとおりです。

  • OS:Rocky Linux 9

  • MySQL:9.7.1

  • CPU:8コア

  • メモリ:32GB

  • ストレージ:SSD

my.cnf は最低限以下の設定を行いました。

計測方針

今回の検証では以下の方針を採用しました:

  • Buffer Pool サイズのみを変更

    • 4, 8, 12, 16, 20, 24, 28, 31GB

  • HammerDB(TPROC‑C)を1時間

  • Prometheus で内部メトリクスを記録

この方法により、
「Buffer Pool を増やすとどこまで性能が上がり、どこから下がるのか」
を定量的に判断したいと思います。

Prometheus と Exporter のインストール

Prometheus の設定、mysqld_exporter のユーザー作成、サービス起動などを行い、 MySQL のメトリクスを9104ポートから収集できるようにしました。

Node Exporter も同様にインストールし、9100ポートから収集できるように設定しました。

Prometheusのインストール

Prometheusの起動。

mysqld_exporterのインストール

MySQL に exporter 用ユーザーを作成。

Exporter の設定。

/etc/systemd/system/mysqld_exporter.service

mysqld_exporter を起動。

ポート 9104 で MySQL のメトリクスが公開され。 Prometheus が自動収集を開始します。

node_exporterのインストール


HammerDB(TPROC‑C)による負荷生成

OLTP 系の性能を測るため、HammerDB の TPROC‑C を使用しました。

HammerDB のインストール

MySQL 用ユーザー作成。

スキーマ構築

HammerDB のインストール、ユーザー作成、スキーマ構築(1000 Warehouse)を行いました。

1000 Warehouseで大体130GBほどのデータが生成されました。

負荷実行設定

負荷実行設定(Rampup 2分 + 60分の本負荷)を行いました。


Prometheus によるメトリクス収集

Prometheus + mysqld_exporter を用いて、以下のメトリクスを収集しました。

  • mysql_global_status_innodb_buffer_pool_reads

  • mysql_global_status_innodb_buffer_pool_read_requests

  • mysql_global_status_innodb_buffer_pool_bytes_dirty

  • mysql_global_status_innodb_buffer_pool_bytes_data

  • mysql_global_status_innodb_buffer_pool_read_ahead_rnd

  • mysql_global_status_innodb_buffer_pool_read_ahead_evicted

  • mysql_global_status_innodb_buffer_pool_read_ahead

計測の自動化

Buffer Pool サイズを変更しながら HammerDB をループ実行するため、
以下のような自動化スクリプトを使用しました。

Prometheus 側には bp_size というラベルを付与し、
Buffer Pool サイズごとにメトリクスを比較できるようにしました。

(要点のみ抜粋)

/etc/prometheus/prometheus.yml



HammerDB の結果(NOPM / TPM)

Buffer Pool サイズを段階的に変更しながら、
HammerDB(TPROC‑C)で 1時間の負荷をかけた結果は以下のとおりです。

Buffer Pool

NOPM

TPM

4GB

20,641

47,937

8GB

18,991

44,093

12GB

18,889

43,895

16GB

25,499

59,183

20GB

35,028

81,365

24GB

36,744

85,321

28GB

38,997

90,572

31GB

35,053

81,434

NOPM(New Orders Per Minute/新規注文処理数)と TPM(Transactions Per Minute/トランザクション数)はTPROC‑C の性能指標です。

結果の傾向

Buffer Pool を増やすにつれて NOPM / TPM は上昇しました。
特に 20GB 以降で伸びが大きくなり、ワーキングセットが Buffer Pool に収まり始めた可能性があります。

NOPM / TPM が最大となったのは 28GB でした。
データページのキャッシュ効率が最も高く、物理読み込みが最小化されたと考えられます。

31GB に増やすと性能が低下しました。
このことから、Buffer Pool は大きすぎても性能が落ちる場合があると判断できます。

グラフ化すると、性能曲線は一定サイズまでは改善し、その後は悪化する山型の形状です。


Prometheus メトリクスの分析

HammerDB の結果だけでも Buffer Pool の最適値はある程度見えてきますが、
内部メトリクスを観測することで 「なぜそのサイズが最適なのか」 をより正確に理解できるようになります。

mysqld_exporterメトリクスの分析

MySQL GLOBAL STATUSのメトリクスです。

物理読み込み(innodb_buffer_pool_reads)

最も重要な指標です。
InnoDB がディスクからページを読み込んだ回数を示します。 Buffer Pool に収まらないデータが多いほど物理読み込みが増え、ディスク I/O が増加します。

始めのうちは急激なスパイクが見られますが、その後はなだらかな下降となっています。

Buffer Pool が小さいほど物理読み込みが多く、 特に 4GB は常に高い増加量を示していました。 ディスク I/O が増えるため、性能に大きく影響します。

Data ページ量(innodb_buffer_pool_bytes_data)

Buffer Pool 内に保持されているデータページの総量です。

4GB〜20GBではある時点で頭打ちになりました。24GB以上では、ワーキングセットが収まっており、 Data ページ量は増加の一途です。

TPCC 1000 warehouse(約130GB)を用意しましたが、 実際のワーキングセットは 24GB の Buffer Pool に収まっていたようです。

ダーティページ率(innodb_buffer_pool_bytes_dirty / innodb_buffer_pool_bytes_data)

変更済みでまだディスクへ書き戻されていないページの割合です。

Buffer Pool が小さいほどダーティページ率が高くなり、 書き込み負荷が増加していました。 これは redo/doublewrite の負荷増加につながります。

Buffer Pool ヒット率(1 – (innodb_buffer_pool_reads / innodb_buffer_pool_reads_requests))

読み込み要求が Buffer Pool 内で完結した割合です。

どの Buffer Pool サイズでも 99〜100%で横並びとなり、 Buffer Pool サイズによる差はほとんど見られませんでした。 ワーキングセットが比較的コンパクトであることを示しています。

read-ahead evicted(innodb_buffer_pool_read_ahead_evicted)

先読みで読み込んだページがすぐに追い出された回数です。

4GB のときだけ発生していました。 8GB 以上ではワーキングセットが収まり、 read-ahead で読み込んだページがすぐ追い出されることはありませんでした。


mysqld_exporter のメトリクスから、 ワーキングセットは 24GB 程度で収まっており、Buffer Pool をそれ以上にしても効果が限定的である
ということが読み取れます。

node_exporterメトリクスの分析

続いてOSのメトリクスです。

I/O待ち時間(node_cpu_seconds_total, mode=iowait)

iowait はディスク I/O の待ち時間を示す指標です。

今回の検証では、どの Buffer Pool サイズでも iowait はなだらかに増加するだけで、 瞬間的な I/O づまりは発生していませんでした。 ただし、Buffer Pool が大きくなるほど OS のページキャッシュが圧迫されるため、 I/O の平均速度は少しずつ悪化していると考えられます。

スワップアウト(node_vmstat_pswpout)

OS がメモリ不足になった瞬間にページをスワップへ追い出した回数です。

グラフでは、Buffer Pool が大きい設定ほど 途中で階段状に跳ね上がる箇所が見られます。 これは、負荷中に OS がページキャッシュを増やしたいタイミングでメモリ不足が発生し、 kswapd が追加のスワップアウトを実行した瞬間を示しています。

スワップイン(node_vmstat_pswpin)

スワップに追い出されたページを再びメモリに読み戻した回数です。

Buffer Pool が大きいほど pswpin が増加し、 特に 24GB 以上 では負荷中に階段状の増加が目立ちます。 これは、必要なページがスワップに押し出されてしまい、 処理のために読み戻しが発生している状態です。

最適な Buffer Pool の考え方

今回の結果を総合すると、 Buffer Pool の最適値は「ワーキングセットが収まり、かつ OS のページキャッシュを奪いすぎない」サイズです。

具体的には次のように考えられます。

20GB までは効果がある

  • ワーキングセットが収まる

  • 物理読み込みが減る

  • ダーティページ率も安定

  • OS のページキャッシュも十分残る。

  • MySQL と OS のバランスが良い

24GB を超えると OS が苦しくなる

  • pswpout が増加(メモリ不足の瞬間)

  • pswpin が負荷中に発生(性能劣化の直接要因)

  • OS ページキャッシュが枯渇

  • 性能が低下し始める


まとめ:OS・MySQL・性能指標の3点から見た Buffer Pool の最適値

今回、Buffer Pool を 4GB〜31GB まで段階的に変更し、 HammerDB(TPROC‑C)で 1時間の負荷をかけて性能を測定しました。 同時に mysqld_exporter と node_exporter のメトリクスを収集し、 OS と MySQL の両面から挙動を確認しました。

HammerDB(TPROC‑C)の性能は 28GB がピークで、 31GB にすると逆に性能が落ちています。

MySQL のメトリクスから、 ワーキングセットは 20GB 程度で十分であることが分かります。

HammerDB のワーキングセットは一定ですが、本番環境ではより複雑に変動します。今回の検証が、あなたの環境で Buffer Pool を見直す際の一助となれば幸いです。

スマートスタイルTECHブログについて

スマートスタイルTECHブログでは、日頃MySQLのサポート業務に従事している有資格者で構成された技術サポートチームがMySQLに関する技術情報を発信しています。データベースのお困りごとはお気軽にご相談下さい。

よかったらシェアしてね!
  • URLをコピーしました!
目次