T-CREATOR

MySQL キャパシティプランニング:Buffer Pool/IOPS/接続数の見積もり術

MySQL キャパシティプランニング:Buffer Pool/IOPS/接続数の見積もり術

MySQL データベースのパフォーマンスを最大限に引き出すには、適切なキャパシティプランニングが不可欠です。本記事では、MySQL における 3 つの重要なリソース指標である「Buffer Pool」「IOPS」「接続数」の見積もり方法を、実践的な計算式とともに解説します。

これらの指標を正しく見積もることで、システムのボトルネックを未然に防ぎ、安定したデータベース運用を実現できるでしょう。初心者の方にもわかりやすく、具体的な数値例を交えながらご説明していきますね。

背景

MySQL におけるキャパシティプランニングの重要性

データベースシステムは、アプリケーションの心臓部として機能します。適切なリソース配分がなされていないと、レスポンスタイムの遅延やシステムダウンといった深刻な問題を引き起こすでしょう。

MySQL では、メモリ、ディスク I/O、ネットワーク接続という 3 つの主要リソースを効果的に管理する必要があります。特に InnoDB ストレージエンジンを使用する場合、これらのリソース配分がパフォーマンスに直結するのです。

以下の図は、MySQL のリソース管理における主要な要素とその関係性を示しています。

mermaidflowchart TB
    app["アプリケーション"] -->|SQL クエリ| conn["接続管理<br/>max_connections"]
    conn -->|クエリ実行| bp["Buffer Pool<br/>メモリキャッシュ"]
    bp -->|キャッシュミス| disk["ディスク I/O<br/>IOPS"]
    disk -->|データ読み込み| bp
    bp -->|結果返却| conn
    conn -->|レスポンス| app

    style bp fill:#e1f5ff
    style disk fill:#fff4e1
    style conn fill:#f0ffe1

この図からわかるように、接続管理、Buffer Pool、ディスク I/O は相互に影響し合っています。

キャパシティプランニングで考慮すべき 3 大要素

Buffer Pool:データキャッシュの要

InnoDB Buffer Pool は、テーブルデータとインデックスをメモリ上にキャッシュする領域です。ディスクアクセスは非常に遅いため、頻繁にアクセスされるデータをメモリに保持することで、劇的なパフォーマンス向上が期待できますね。

IOPS:ディスク性能の指標

IOPS(Input/Output Operations Per Second)は、1 秒間に実行できるディスク読み書き操作の回数を表します。Buffer Pool でカバーできないデータアクセスは、すべてディスク I/O として発生するでしょう。

接続数:同時アクセスの上限

MySQL への同時接続数は、max_connections パラメータで制御されます。接続数が不足すると、新規接続が拒否され、アプリケーションエラーが発生してしまいます。

課題

キャパシティプランニングにおける一般的な問題点

データベースのキャパシティプランニングを行う際、多くの開発者や運用担当者が直面する課題があります。これらの課題を理解することで、適切な見積もり手法の必要性が明確になるでしょう。

過剰なリソース配分によるコスト増大

「とりあえず大きめに」という姿勢でリソースを配分すると、クラウド環境では特に無駄なコストが発生します。例えば、実際には 16GB で十分なところを 64GB のメモリインスタンスを選択してしまうケースは珍しくありません。

月額コストで見ると、この差は数万円から数十万円にも及ぶことがあるのです。

不足するリソースによるパフォーマンス劣化

逆に、リソースを過小評価すると深刻なパフォーマンス問題を引き起こします。Buffer Pool が小さすぎると、頻繁にディスクアクセスが発生し、クエリ実行時間が 10 倍以上に膨れ上がることもあるでしょう。

IOPS が不足すれば、ディスク I/O 待ちでシステム全体が停滞してしまいます。

以下の図は、リソース配分の問題がどのようにパフォーマンスに影響するかを示しています。

mermaidflowchart LR
    subgraph over["過剰配分"]
        over_mem["メモリ 64GB<br/>(実需 16GB)"] -->|無駄| over_cost["コスト増大<br/>月額 +30万円"]
    end

    subgraph under["過小配分"]
        under_mem["Buffer Pool 4GB<br/>(実需 16GB)"] -->|不足| under_perf["ディスクアクセス増<br/>レスポンス 10倍悪化"]
    end

    subgraph optimal["適正配分"]
        opt_mem["メモリ 16GB"] -->|最適化| opt_result["コストとパフォーマンスの<br/>バランス達成"]
    end

    style over_cost fill:#ffcccc
    style under_perf fill:#ffcccc
    style opt_result fill:#ccffcc

適正なリソース配分を実現するには、科学的な見積もり手法が必要不可欠です。

成長予測の困難さ

サービスの成長に伴い、データベースの負荷も増大します。しかし、どの程度の成長率を見込むべきか、判断が難しいことも課題の一つでしょう。

3 ヶ月後にユーザー数が 2 倍になるのか、半年後に 5 倍になるのか、これらの予測精度がキャパシティプランニングの成否を分けます。

複数リソース間の相互依存性

Buffer Pool、IOPS、接続数は独立して存在するのではなく、相互に影響し合います。例えば、接続数を増やすと、それに伴い Buffer Pool の使用量も増加するでしょう。

このような相互依存性を考慮しないと、一部のリソースだけを増強しても、ボトルネックが別の場所に移動するだけという結果になりかねません。

見積もり不足が引き起こす具体的なトラブル

Error 1040: Too many connections

接続数の見積もりが不足すると、以下のようなエラーが発生します。

textError 1040 (HY000): Too many connections

このエラーは、max_connections の上限に達したときに発生し、新規接続が拒否されます。

発生条件

  • 現在の接続数が max_connections の値に達している
  • アプリケーション側で接続プールの設定が不適切
  • 長時間実行されるクエリが接続を占有している

解決方法

  1. 現在の接続数を確認する:SHOW PROCESSLIST;
  2. max_connections の値を確認する:SHOW VARIABLES LIKE 'max_connections';
  3. 適切な値に調整する:SET GLOBAL max_connections = 500;

Buffer Pool サイズ不足によるパフォーマンス低下

Buffer Pool が小さすぎると、以下のような症状が現れます。

sql-- Buffer Pool の効率を確認するクエリ
SHOW GLOBAL STATUS LIKE 'Innodb_buffer_pool_read%';
text+---------------------------------------+-------------+
| Variable_name                         | Value       |
+---------------------------------------+-------------+
| Innodb_buffer_pool_read_requests      | 1000000000  |
| Innodb_buffer_pool_reads              | 50000000    |
+---------------------------------------+-------------+

この例では、ディスクからの読み込み(Innodb_buffer_pool_reads)が全体の 5% を占めており、Buffer Pool ヒット率が 95% であることを示しています。理想的には 99% 以上を目指すべきでしょう。

解決策

Buffer Pool サイズの見積もり方法

Buffer Pool は InnoDB の最も重要なメモリ領域です。適切なサイズを見積もることで、ディスクアクセスを最小限に抑え、クエリパフォーマンスを最大化できます。

ワーキングセット方式による見積もり

ワーキングセットとは、頻繁にアクセスされるデータの集合を指します。全データをメモリに載せる必要はなく、ワーキングセットをカバーできれば十分なパフォーマンスが得られるでしょう。

以下のクエリで、実際のデータサイズを確認できます。

sql-- データベース全体のサイズを確認
SELECT
    table_schema AS 'Database',
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS 'Size (MB)'
FROM
    information_schema.tables
GROUP BY
    table_schema;

このクエリは、各データベースのデータとインデックスの合計サイズを MB 単位で表示します。

次に、テーブルごとの詳細なサイズを確認しましょう。

sql-- テーブルごとのサイズを確認
SELECT
    table_name AS 'Table',
    ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'Size (MB)',
    ROUND((data_length / 1024 / 1024), 2) AS 'Data (MB)',
    ROUND((index_length / 1024 / 1024), 2) AS 'Index (MB)'
FROM
    information_schema.tables
WHERE
    table_schema = 'your_database_name'
ORDER BY
    (data_length + index_length) DESC;

このクエリで、どのテーブルが大きいのか、またインデックスがどの程度のサイズを占めているのかが明確になります。

Buffer Pool サイズの計算式

基本的な計算式は以下の通りです。

textBuffer Pool サイズ = ワーキングセットサイズ × 1.2 〜 1.5

係数 1.2 〜 1.5 は、以下の要素を考慮した安全マージンです:

  • データの成長予測
  • インデックスの追加
  • 一時テーブルの使用

例えば、ワーキングセットが 10GB の場合、Buffer Pool は 12GB 〜 15GB に設定すると良いでしょう。

物理メモリとの関係

サーバーの物理メモリ全体から Buffer Pool に割り当てる割合の目安は以下の通りです。

サーバー用途Buffer Pool 割合例(物理メモリ 32GB の場合)
MySQL 専用サーバー70〜80%22GB 〜 26GB
他サービス共存50〜60%16GB 〜 19GB
開発環境30〜40%10GB 〜 13GB

MySQL 専用サーバーの場合、物理メモリの約 70〜80% を Buffer Pool に割り当てるのが一般的です。残りのメモリは、OS のファイルシステムキャッシュや他の MySQL メモリ領域(ソートバッファ、接続バッファなど)に使用されます。

設定方法は以下の通りです。

ini# my.cnf または my.ini での設定例
[mysqld]
innodb_buffer_pool_size = 16G

このパラメータは MySQL の起動時にのみ適用されるため、変更後は再起動が必要です。

IOPS の見積もり方法

IOPS(Input/Output Operations Per Second)は、ディスクが 1 秒間に処理できる読み書き操作の回数です。適切な IOPS を見積もることで、ディスク I/O がボトルネックになることを防げます。

IOPS 必要量の計算式

IOPS 必要量は、以下の要素から算出できます。

text必要 IOPS = (読み取り操作/秒) + (書き込み操作/秒) × 書き込みペナルティ

書き込みペナルティは、ストレージの種類によって異なります:

  • SSD:1.0 〜 1.5
  • HDD(RAID 10):2
  • HDD(RAID 5):4
  • HDD(RAID 6):6

以下の図は、IOPS 計算における要素の関係性を示しています。

mermaidflowchart TD
    query["SQL クエリ"] --> read_ops["読み取り操作/秒"]
    query --> write_ops["書き込み操作/秒"]

    read_ops --> read_iops["読み取り IOPS"]
    write_ops --> write_penalty["書き込みペナルティ<br/>(ストレージ種類依存)"]
    write_penalty --> write_iops["書き込み IOPS"]

    read_iops --> total["総必要 IOPS"]
    write_iops --> total

    storage["ストレージ種類"] -.->|影響| write_penalty

    style total fill:#e1f5ff
    style storage fill:#fff4e1

この図からわかるように、ストレージの種類が書き込みペナルティに大きく影響します。

現在の IOPS を測定する方法

MySQL で現在の I/O 状況を確認するには、以下のクエリを使用します。

sql-- InnoDB の I/O 統計を確認
SHOW GLOBAL STATUS LIKE 'Innodb_data_%';

このクエリは、InnoDB のデータ読み書きに関する各種統計情報を表示します。

より詳細な情報を取得するには、Performance Schema を使用しましょう。

sql-- ファイル I/O の詳細統計(Performance Schema が有効な場合)
SELECT
    file_name,
    SUM_NUMBER_OF_BYTES_READ / 1024 / 1024 AS 'Read (MB)',
    SUM_NUMBER_OF_BYTES_WRITE / 1024 / 1024 AS 'Write (MB)',
    COUNT_READ,
    COUNT_WRITE
FROM
    performance_schema.file_summary_by_instance
WHERE
    file_name LIKE '%ibd%'
ORDER BY
    (SUM_NUMBER_OF_BYTES_READ + SUM_NUMBER_OF_BYTES_WRITE) DESC
LIMIT 10;

このクエリで、どのファイルに対する I/O が多いかを特定できます。

ピークタイムを考慮した見積もり

IOPS は平均値ではなく、ピークタイムの値で見積もる必要があります。以下の計算式を使用しましょう。

text必要 IOPS = 平均 IOPS × ピーク係数 × 安全マージン

ピーク係数 = ピーク時の負荷 / 平均負荷(通常 2〜5)
安全マージン = 1.3 〜 1.5

例えば、平均 IOPS が 1000 で、ピーク時に 3 倍の負荷がかかる場合は以下のようになります。

text必要 IOPS = 1000 × 3 × 1.3 = 3900 IOPS

安全を見て 4000 IOPS 以上のストレージを選択すると良いでしょう。

接続数の見積もり方法

MySQL への同時接続数は、max_connections パラメータで制御されます。適切な値を設定することで、接続エラーを防ぎつつ、メモリの無駄遣いを避けられます。

接続数の計算式

基本的な計算式は以下の通りです。

textmax_connections = (アプリケーションサーバー数) × (サーバーあたりの接続プール数) × 安全マージン

安全マージンは通常 1.2 〜 1.5 を使用します。

例えば、以下のような構成の場合を考えてみましょう。

項目
アプリケーションサーバー数5 台
サーバーあたりの接続プール20 接続
安全マージン1.3

計算すると以下のようになります。

textmax_connections = 5 × 20 × 1.3 = 130 接続

余裕を見て 150 接続に設定すると良いでしょう。

接続数に関連するメモリ使用量

各接続は一定量のメモリを消費します。接続ごとのメモリ使用量は、以下のパラメータで決まります。

sql-- 接続あたりのメモリ関連パラメータを確認
SHOW VARIABLES LIKE 'read_buffer_size';
SHOW VARIABLES LIKE 'read_rnd_buffer_size';
SHOW VARIABLES LIKE 'sort_buffer_size';
SHOW VARIABLES LIKE 'join_buffer_size';
SHOW VARIABLES LIKE 'thread_stack';

これらの値を合計すると、1 接続あたりのメモリ使用量が算出できます。

一般的な設定での概算は以下の通りです。

text1 接続あたりのメモリ =
    read_buffer_size (128KB)
  + read_rnd_buffer_size (256KB)
  + sort_buffer_size (256KB)
  + join_buffer_size (256KB)
  + thread_stack (256KB)
  ≈ 1〜2MB

したがって、接続数に応じたメモリ確保が必要になります。

text接続用メモリ = max_connections × 1〜2MB

150 接続の場合、150MB 〜 300MB のメモリが接続用に必要です。

現在の接続状況を確認する方法

現在の接続数と最大接続数の履歴を確認するには、以下のクエリを使用します。

sql-- 現在の接続数を確認
SHOW STATUS LIKE 'Threads_connected';
sql-- これまでの最大同時接続数を確認
SHOW STATUS LIKE 'Max_used_connections';
sql-- 設定されている max_connections を確認
SHOW VARIABLES LIKE 'max_connections';

Max_used_connectionsmax_connections に近い値の場合、接続数が不足している可能性があります。

理想的には、Max_used_connectionsmax_connections の 70〜80% 程度に収まっているのが望ましいでしょう。

具体例

ケーススタディ:中規模 EC サイトのキャパシティプランニング

実際のケースを通じて、Buffer Pool、IOPS、接続数の見積もりプロセスを見ていきましょう。以下の条件を持つ EC サイトを想定します。

システム構成と要件

項目
月間アクティブユーザー50 万人
1 日あたりの注文数5000 件
データベースサイズ合計 80GB
アプリケーションサーバー3 台
ピークタイム20:00〜22:00(通常の 4 倍)

以下の図は、このシステムの全体構成と各リソースの関係性を示しています。

mermaidflowchart TB
    users["ユーザー<br/>(月間 50万人)"] -->|ピーク時 4倍| lb["ロードバランサー"]
    lb --> app1["App Server 1<br/>接続プール: 30"]
    lb --> app2["App Server 2<br/>接続プール: 30"]
    lb --> app3["App Server 3<br/>接続プール: 30"]

    app1 --> mysql["MySQL Server<br/>データサイズ: 80GB"]
    app2 --> mysql
    app3 --> mysql

    mysql --> bp["Buffer Pool<br/>(見積もり対象)"]
    mysql --> iops["IOPS<br/>(見積もり対象)"]
    mysql --> conn["max_connections<br/>(見積もり対象)"]

    style bp fill:#e1f5ff
    style iops fill:#fff4e1
    style conn fill:#f0ffe1

この構成に対して、3 つのリソースを順に見積もっていきます。

Buffer Pool サイズの見積もり実例

ステップ 1:データサイズの詳細確認

まず、実際のデータ分布を確認します。

sql-- データベースごとのサイズを確認
SELECT
    table_schema AS 'Database',
    ROUND(SUM(data_length + index_length) / 1024 / 1024 / 1024, 2) AS 'Size (GB)'
FROM
    information_schema.tables
GROUP BY
    table_schema;

実行結果(例):

text+------------------+-----------+
| Database         | Size (GB) |
+------------------+-----------+
| ec_shop_db       | 65.00     |
| ec_analytics_db  | 12.00     |
| ec_session_db    | 3.00      |
+------------------+-----------+

合計約 80GB ですが、全てを Buffer Pool に載せる必要はありません。

ステップ 2:ワーキングセットの特定

EC サイトの場合、頻繁にアクセスされるデータは以下の通りです。

テーブル種類サイズアクセス頻度Buffer Pool 必要性
商品マスタ15GB非常に高い必須
在庫情報2GB非常に高い必須
注文データ(直近 3 ヶ月)8GB高い必須
顧客情報(アクティブユーザー)5GB高い必須
注文データ(過去分)35GB低い不要
アクセスログ15GB低い不要

ワーキングセット = 15 + 2 + 8 + 5 = 30GB

ステップ 3:Buffer Pool サイズの決定

計算式を適用します。

textBuffer Pool サイズ = ワーキングセット × 1.3(成長余裕)
                   = 30GB × 1.3
                   = 39GB

余裕を見て 40GB に設定するのが適切でしょう。

ステップ 4:物理メモリの決定

Buffer Pool 40GB に対して、物理メモリを決定します。

text必要物理メモリ = Buffer Pool ÷ 0.75(MySQL 専用サーバーの場合)
               = 40GB ÷ 0.75
               = 53.3GB

実際のインスタンス選択では 64GB メモリ のサーバーを選択するのが適切です。

設定ファイルは以下のようになります。

ini# /etc/my.cnf での設定
[mysqld]
innodb_buffer_pool_size = 40G
innodb_buffer_pool_instances = 8

innodb_buffer_pool_instances は、Buffer Pool を複数の領域に分割して並列性を高めるパラメータです。Buffer Pool が 1GB 以上の場合、設定することをお勧めします。

IOPS の見積もり実例

ステップ 1:現在の I/O 状況の測定

まず、現在の I/O 状況を確認します。

sql-- 1 秒あたりの読み書き操作を計算
SELECT
    'Read Operations/sec' AS Metric,
    (SELECT VARIABLE_VALUE FROM performance_schema.global_status
     WHERE VARIABLE_NAME = 'Innodb_data_reads') /
    (SELECT VARIABLE_VALUE FROM performance_schema.global_status
     WHERE VARIABLE_NAME = 'Uptime') AS Value
UNION ALL
SELECT
    'Write Operations/sec' AS Metric,
    (SELECT VARIABLE_VALUE FROM performance_schema.global_status
     WHERE VARIABLE_NAME = 'Innodb_data_writes') /
    (SELECT VARIABLE_VALUE FROM performance_schema.global_status
     WHERE VARIABLE_NAME = 'Uptime') AS Value;

実行結果(例):

text+------------------------+---------+
| Metric                 | Value   |
+------------------------+---------+
| Read Operations/sec    | 250.00  |
| Write Operations/sec   | 150.00  |
+------------------------+---------+

これは平常時の値です。ピークタイムには 4 倍の負荷がかかります。

ステップ 2:ピーク時の IOPS 計算

ピーク時の値を算出します。

textピーク時読み取り = 250 × 4 = 1000 ops/sec
ピーク時書き込み = 150 × 4 = 600 ops/sec

SSD を使用する前提で、書き込みペナルティを 1.2 とします。

text必要 IOPS = 1000 + (600 × 1.2) = 1000 + 720 = 1720 IOPS

ステップ 3:安全マージンの適用

将来の成長を見込んで、安全マージン 1.5 を適用します。

text推奨 IOPS = 1720 × 1.5 = 2580 IOPS

最低 3000 IOPS のストレージを選択するのが適切でしょう。

クラウドサービスでのストレージ選択例(AWS の場合):

ストレージタイプIOPS用途
gp3(汎用 SSD)3000〜16000推奨 ★★★
io2(プロビジョンド IOPS)最大 64000高負荷時
gp2(旧世代)最大 16000非推奨

この例では、gp3 で 3000 IOPS を設定すれば十分です。

接続数の見積もり実例

ステップ 1:アプリケーション側の接続設定確認

各アプリケーションサーバーの接続プール設定を確認します。

javascript// Node.js での接続プール設定例(mysql2 ライブラリ)
const mysql = require('mysql2/promise');

const pool = mysql.createPool({
  host: 'mysql-server.example.com',
  user: 'app_user',
  password: 'password',
  database: 'ec_shop_db',
  waitForConnections: true,
  connectionLimit: 30, // サーバーあたりの最大接続数
  queueLimit: 0,
});

この設定では、各アプリケーションサーバーから最大 30 接続が確立されます。

ステップ 2:総接続数の計算

システム全体での接続数を計算します。

text通常時の接続数 = アプリサーバー数 × 接続プール数
               = 3 × 30
               = 90 接続

ピーク時にはアプリケーションサーバーがスケールアウトする可能性を考慮します。

textピーク時のアプリサーバー数 = 3 × 1.5(スケール想定) = 4.5 ≈ 5 台
ピーク時の接続数 = 5 × 30 = 150 接続

ステップ 3:管理用接続とバッチ処理の考慮

通常の接続に加えて、以下の接続も考慮する必要があります。

用途接続数
監視ツール5
バックアップ処理2
バッチ処理10
管理者用接続5
予備8

追加接続数 = 30 接続

ステップ 4:max_connections の決定

textmax_connections = ピーク時接続数 + 追加接続数 + 安全マージン
                = 150 + 30 + (180 × 0.2)
                = 216 接続

余裕を見て 250 接続 に設定するのが適切です。

設定方法は以下の通りです。

ini# /etc/my.cnf での設定
[mysqld]
max_connections = 250

ステップ 5:接続用メモリの確認

接続数に応じたメモリ消費を確認しましょう。

text接続用メモリ = 250 × 2MB(1 接続あたり)
             = 500MB
             = 0.5GB

64GB の物理メモリから見ると、わずか 0.8% 程度なので問題ありません。

総合的なリソース配分表

以下の表は、今回のケーススタディでの最終的なリソース配分をまとめたものです。

リソース項目見積もり値実装値物理メモリ比率
Buffer Pool39GB40GB62.5%
接続用メモリ0.5GB0.5GB0.8%
その他 MySQL メモリ3GB3GB4.7%
OS・ファイルキャッシュ20GB20.5GB32.0%
合計物理メモリ62.5GB64GB100%
IOPS 項目
平常時必要 IOPS430
ピーク時必要 IOPS1720
安全マージン適用後2580
実装 IOPS3000
接続数項目
通常時接続数90
ピーク時接続数150
追加接続数30
max_connections250

このように、各リソースを科学的に見積もることで、適切なインフラ構成を決定できます。

継続的なモニタリングと調整

キャパシティプランニングは一度行えば終わりではありません。定期的にモニタリングし、必要に応じて調整することが重要です。

Buffer Pool の効率モニタリング

sql-- Buffer Pool のヒット率を確認(週次で確認推奨)
SELECT
    (1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)) * 100
    AS 'Buffer Pool Hit Rate (%)'
FROM
    (SELECT VARIABLE_VALUE AS Innodb_buffer_pool_reads
     FROM performance_schema.global_status
     WHERE VARIABLE_NAME = 'Innodb_buffer_pool_reads') AS reads,
    (SELECT VARIABLE_VALUE AS Innodb_buffer_pool_read_requests
     FROM performance_schema.global_status
     WHERE VARIABLE_NAME = 'Innodb_buffer_pool_read_requests') AS requests;

ヒット率が 95% を下回る場合は、Buffer Pool サイズの増加を検討しましょう。

IOPS 使用率のモニタリング

クラウド環境では、プロバイダーのモニタリングツールで IOPS 使用率を確認できます。80% を超える時間帯が頻繁にある場合は、IOPS の増加が必要です。

接続数のモニタリング

sql-- 接続数の使用状況を確認(日次で確認推奨)
SELECT
    (SELECT VARIABLE_VALUE FROM performance_schema.global_status
     WHERE VARIABLE_NAME = 'Max_used_connections') AS 'Max Used',
    (SELECT VARIABLE_VALUE FROM performance_schema.global_variables
     WHERE VARIABLE_NAME = 'max_connections') AS 'Max Configured',
    ROUND((SELECT VARIABLE_VALUE FROM performance_schema.global_status
           WHERE VARIABLE_NAME = 'Max_used_connections') /
          (SELECT VARIABLE_VALUE FROM performance_schema.global_variables
           WHERE VARIABLE_NAME = 'max_connections') * 100, 2) AS 'Usage (%)';

使用率が 80% を超える場合は、max_connections の増加を検討する必要があります。

まとめ

MySQL のキャパシティプランニングは、Buffer Pool、IOPS、接続数という 3 つの主要リソースを科学的に見積もることが基本となります。それぞれのリソースには明確な計算方法があり、システムの特性に応じて適切な値を導き出せるのです。

本記事で学んだポイント

Buffer Pool の見積もりでは、全データサイズではなくワーキングセット(頻繁にアクセスされるデータ)を基準とし、1.2〜1.5 倍の安全マージンを適用します。物理メモリの 70〜80% を Buffer Pool に割り当てることで、最適なパフォーマンスが得られるでしょう。

IOPS の見積もりでは、平常時ではなくピークタイムの値を基準とし、ストレージの種類に応じた書き込みペナルティを考慮する必要があります。安全マージン 1.3〜1.5 を適用することで、将来の成長にも対応できます。

接続数の見積もりでは、アプリケーションサーバー数と接続プール設定から基本値を算出し、管理用接続やバッチ処理用の接続を加算します。max_connections は接続用メモリも消費するため、物理メモリとのバランスを考慮することが重要です。

実践のための具体的な手順

  1. 現状の把握:まず、データサイズ、I/O 状況、接続数の現状を SQL クエリで確認しましょう
  2. ワーキングセットの特定:全データではなく、頻繁にアクセスされるデータを特定します
  3. ピーク時の負荷計測:平常時ではなく、ピーク時の負荷を基準に見積もることが重要です
  4. 安全マージンの適用:将来の成長を見込んで、1.2〜1.5 倍の余裕を持たせましょう
  5. 継続的なモニタリング:設定後も定期的に監視し、必要に応じて調整します

キャパシティプランニングの継続的改善

キャパシティプランニングは一度実施して終わりではありません。サービスの成長に応じて、定期的に見直すことが必要です。

モニタリングツールで以下の指標を継続的に監視し、閾値を超えた場合は速やかに調整しましょう:

  • Buffer Pool ヒット率(目標:99% 以上)
  • IOPS 使用率(目標:80% 以下)
  • 接続数使用率(目標:80% 以下)

これらの指標を定期的にレビューすることで、パフォーマンス問題を未然に防ぎ、コスト効率の高いインフラ運用が実現できるのです。

適切なキャパシティプランニングにより、安定したデータベース運用とコスト最適化の両立が可能になります。本記事でご紹介した手法を、ぜひ実際のプロジェクトで活用してみてください。

関連リンク