数字の重圧:なぜパフォーマンスを「勘」に頼ってはいけないのか?
1,000ユーザーで快適に動作しているアプリが、ユーザー数が10,000に急増したときに「ダウン」しないと言い切れますか?勘に頼るのはやめましょう。上司がサーバーのアップグレード(4コア 8GB RAMからそれ以上の構成へ)を承認した際、パフォーマンスが実際にどれほど向上したかを証明するための数値が必要になります。
以前、非常に神経を使う案件を担当しました。100GBのデータをMySQLからPostgreSQLへ移行するというものです。計画に3日、実行に1日を費やしました。その時の最大の懸念は、データの移行方法ではなく、「新しいシステムは以前と同じように負荷に耐えられるのか?」ということでした。これに答えるため、私は高トラフィックWebサイト向けデータベース性能最適化の重要性を再認識し、感覚ではなくsysbenchの数値を利用しました。
sysbenchは、OLTP型のデータベースベンチマークを行うための非常に強力なオープンソースツールです。数千の同時トランザクションをシミュレートし、データベースを限界状態まで追い込みます。これにより、CPU、RAM、あるいはディスクI/Oのボトルネックが明確に浮き彫りになります。
Linuxへのsysbenchのインストール
ほとんどのLinuxディストリビューションでは、公式リポジトリにsysbenchが用意されています。インストールは数秒で完了します。
Ubuntu/Debianの場合:
sudo apt update
sudo apt install sysbench -y
CentOS/RHELの場合:
sudo yum install epel-release -y
sudo yum install sysbench -y
インストール後、sysbench --versionコマンドで確認してください。現在は1.0.x系が最も安定した選択肢です。
標準的な3つのステップ
MySQLでもPostgreSQLでも、sysbenchは常に3つのフェーズで実行されます:Prepare(準備) -> Run(実行) -> Cleanup(後片付け)。
- Prepare: ダミーのテーブル(
sbtest1,sbtest2…など)を作成し、数百万件のレコードを投入します。データセットが小さすぎて(RAMに収まるサイズ)、ディスク負荷がかからない場合、結果は現実的ではなくなってしまいます。 - Run: 読み書きのテストを実行します。スレッド数(threads)、実行時間、トランザクションの種類などをカスタマイズできます。
- Cleanup: 一時テーブルを削除し、ディスク容量を解放します。
MySQLでの実践ベンチマーク
まず、テスト場としてtest_dbという名前の空のデータベースを作成します。
mysql -u root -p -e "CREATE DATABASE test_db;"
ステップ1:データの準備
このコマンドは10個のテーブルを作成し、各テーブルに100万件のレコード(合計約1,000万行)を投入します。
sysbench /usr/share/sysbench/oltp_read_write.lua \
--mysql-db=test_db \
--mysql-user=root \
--mysql-password='your_password' \
--db-driver=mysql \
--tables=10 \
--table-size=1000000 \
prepare
ステップ2:負荷テストの実行
16スレッド同時実行で60秒間テストします。この時のサーバーのCPU使用率を観察してください。
sysbench /usr/share/sysbench/oltp_read_write.lua \
--mysql-db=test_db \
--mysql-user=root \
--mysql-password='your_password' \
--db-driver=mysql \
--tables=10 \
--table-size=1000000 \
--threads=16 \
--time=60 \
--report-interval=10 \
run
覚えておくべきパラメータ:
--threads=16: 16件の同時接続をシミュレートします。--time=60: 1分間実行します。--report-interval=10: 10秒ごとに結果を出力します。
PostgreSQLでのベンチマークは何が違うのか?
PostgreSQL vs MySQLで構文はほぼ同じですが、ドライバーを変更する必要があります。また、システムにlibpqライブラリがインストールされていることを確認してください。
データベースの初期化:
sudo -u postgres psql -c "CREATE USER benchmark_user WITH PASSWORD 'password';"
sudo -u postgres psql -c "CREATE DATABASE benchmark_db OWNER benchmark_user;"
Prepareの実行:
sysbench /usr/share/sysbench/oltp_read_write.lua \
--db-driver=pgsql \
--pgsql-host=localhost \
--pgsql-port=5432 \
--pgsql-user=benchmark_user \
--pgsql-password=password \
--pgsql-db=benchmark_db \
--tables=10 \
--table-size=1000000 \
prepare
runコマンドはMySQLと同様ですが、パラメータを--pgsql-*に変更します。PostgreSQLはトランザクション管理が非常に厳格で、テーブル数が増えると効果が顕著に現れます。
「死活」に関わる重要指標の読み方
出力される大量の数値に圧倒されないでください。以下の3つの重要な行に注目しましょう。
- transactions (TPS): 1秒あたりのトランザクション数。TPSが高いほど、データベースは強力です。例えば、2コアのVPSなら、読み書きテストで通常500〜800 TPS程度になります。
- queries (QPS): 1秒あたりのクエリ(Select, Insert…)の総数。
- latency (ms):
- 95th percentile: これが最も現実的な数値です。95%のクエリがこの時間内に完了したことを意味します。95thが100msを超えると、ユーザーはアプリの遅延をはっきりと感じ始めます。
テスト中のシステム監視
sysbenchの実行中、別のターミナルウィンドウを開いてサーバーの状態を監視してください。本格的な運用では、PostgreSQL監視システムの構築も検討すべきです。
htop: CPUを確認します。CPUが100%なのにTPSが低い場合、クエリにインデックス(Index)が不足している可能性があります。数百万行のデータを扱うなら、PostgreSQLインデックスの適切な使い分けが鍵となります。iostat -xz 1: ディスクの%utilを確認します。これが100%に達しているなら、ディスクがボトルネックです。
実際、RAMを8GBから16GBに増やしてもTPSがほとんど向上しないことがありますが、通常のSSDからNVMeに変更すると、特に書き込みテストにおいてパフォーマンスが劇的に変わります。
現場からのアドバイス
絶対に本番環境(Production)のピーク時間帯にベンチマークを行わないでください。深夜にシステムダウンで上司から呼び出される事態は避けたいはずです。本番と同じ構成のステージング環境(Staging)を構築してテストしましょう。
スレッド数を段階的に増やして(1, 4, 8, 16, 32…)複数回テストすることをお勧めします。これにより、システムの「飽和点」を見つけることができます。スレッドを増やしすぎると、リソースの競合(ロッキング)によってレイテンシが急上昇することもあります。特定のクエリに問題がある場合は、EXPLAIN ANALYZEでPostgreSQLクエリを最適化し、実行計画を確認してください。
最後に、後片付けを忘れないでください:
sysbench /usr/share/sysbench/oltp_read_write.lua --db-driver=mysql ... cleanup
このツールが、「データベースはどの程度の負荷に耐えられるのか?」という問いに自信を持って答える助けになれば幸いです。システムの最適化が成功することを願っています!

