『High Performance MySQL 第4版』を読んだ内容を章ごとにまとめています。
第4章 OSとハードウェアの最適化
概要
MySQLサーバは「最も遅い部品の性能」に制約される。
CPU・メモリ・ストレージ・ネットワークといったハードウェア構成やOS設定の最適化は、クエリチューニングと同等に重要である。
本章では、MySQLの性能を支える基盤部分を理解し、ハードウェアやOSをチューニングする方法を解説する。
特にLinux環境を前提とし、CPUの選定、メモリとディスクのバランス、RAID構成、ネットワーク設定、ファイルシステム、スワップ管理、監視ツールの使い方などを扱う。
MySQLパフォーマンスを制限する要因
主なボトルネック
- CPU:最も一般的なボトルネック。
クエリの並列実行数が多い、または単一クエリのCPU処理時間が長い場合に発生。 - I/O(ディスクアクセス):SSDの普及により、HDD時代ほど致命的ではない。
ディスクがクエリの対象になっても読み込みならそこそこのパフォーマンスを発揮する。(書き込みは依然としてボトルネックになりがち) - メモリ:MySQL に必要以上のメモリを割り当てたり、OS や他プロセス分を考慮しないと、逆にボトルネックになる。詳しくは第5章。
[MEMO]
I/Oボトルネックをアプリ設計で回避するよりも、ハードウェア(SSDやRAM)を増設した方が合理的な場合も多い。
CPUの選定
基本方針
- CPU性能は 低レイテンシ と 高クロック周波数 が重要。
MySQLは単一スレッド性能の影響が大きく、コア数よりもクロック数を優先する。 - クエリが多い環境ではスレッド数に比例してCPU利用率が上昇。
[MEMO]
MySQL 8.0 のクエリ実行エンジンは依然としてシングルスレッド寄りで、一部の内部処理を除き、1クエリが複数コアをフルに使うケースは限定的。
メモリとディスクのバランス
- メモリは“ディスクアクセスを避けるため”にある。
- 読み込み(Read)
- メモリに載っていればディスクに触らず最速
- 書き込み(Write)
- 複数更新をまとめて書き込むことでディスク負荷を激減できる
SSD(ソリッドステートストレージ)
- 現在ではHDDよりもフラッシュメモリ(NVRAM)のSSDが標準。
- ランダムアクセスが圧倒的に速い
- ランダムアクセスが多いMySQLにおいて、SSDの性能差は非常に大きい。
- 同時にたくさんの I/O を処理できる(高い並列性)
- 読み込みは特に速い
- 書き込みが複雑
- 書き換え前に必ず「ブロック単位の消去」が必要(一般的に数百KB〜数MB単位で管理)
- 空ブロックを確保するために、データ整理(Garbage Collection)を行う
RAID最適化
| RAIDレベル | 特徴 | MySQLでの用途 |
|---|---|---|
| RAID 0 | ストライピング。高速だが冗長性なし | 一時領域などの非重要データ |
| RAID 1 | ミラーリング。高い信頼性 | バイナリログや重要なデータ領域 |
| RAID 5 | パリティ分散。リビルドコストが高い | 推奨されない(書き込み遅延大) |
| RAID 10 | RAID 1 + 0。高速かつ安全 | 最適解。多くのMySQL環境で採用 |
[MEMO]
書き込み重視のDBではRAID10が最もバランスが良い。
RAID5は安価だが障害時リビルド中に性能が極端に低下する。
ネットワーク設定
- MySQL はネットワーク遅延に弱い(往復遅延なので全体が遅くなる)
- DNS逆引きが一番ハマりやすい罠 →
skip_name_resolveを使うことでIPベースでアクセスするようになる(名前解決を行わなくなる)のでその分の遅延がなくなる - 大量接続時はローカルポート枯渇に注意 →
ip_local_port_rangeでポート範囲拡張可能
ファイルシステムの選定
- InnoDBの読み書きはファイルを通して行われるため、ファイルシステムの性能が直結する。
- MySQL は ACID(耐久性)を守るため、頻繁に
fsync()(物理ディスク書き込み) を実行する。 - ファイルシステムによっては、MySQLが求めてない不要な書き込みを抑制することができるものもある(例:
noatimeオプションを付けてマウントすると、アクセス時刻更新を抑制して性能を改善できる。) - アクセス時刻(atime)更新
- ディレクトリアクセスの metadata 書き込み
- ジャーナルへの余分なログ書き込み
- OS のページキャッシュ(少なくとも InnoDB のデータページについては、バッファプールと二重キャッシュになりがちなので抑えたい)
推奨ファイルシステム
- XFS:大容量・大規模 DB に強い。
- ext4:小〜中規模 DB なら十分。
- ZFS/Btrfs:スナップショット機能などを備えるが、メモリ消費が多くMySQL用途では非推奨。
メモリ・スワップ設定
MySQL はディスクではなく、メモリ上で“ほぼすべての処理”を行う構造をしている
- メモリ不足
- ページをバッファプールに載せられない
- Dirty Page の flush が増える
- Redo Log が詰まる
- スワップが発生 ← 全処理がディスク速度になるので使い物にならなくなる=実質的な障害
- メモリとディスクの速度差は数千〜数万倍
- スワップを極力使用しない設定
- バッファプールサイズを正しく設定する
innodb_buffer_pool_size = メモリの60〜70%
- OS の swappiness を下げる(Linux)
vm.swappiness=1などでスワップ優先度を下げる(範囲は0から100まで)。
- 不要なプロセスをkill
- メモリ監視
OS監視ツールの活用
- MySQL の遅さは、OS の状態と密接に関係している
- CPU / メモリ / I/O / ネットワーク のいずれかが詰まると全体が遅くなる
- MySQL のチューニングではなく、OSトラブルが原因のケースも多い
- OS 指標を見られるようになると、DB障害の切り分けが一気に速くなる
- CPU
- 指標
- us(ユーザCPU)… MySQL の計算処理
- sy(カーネルCPU)… I/O・ネットワーク処理
- iowait … ディスク待ち
- steal … 仮想環境が CPU を奪っている
- 症状
- クエリが全体的に遅い
- JOIN / ORDER BY が重くなる
- mysqld の CPU が 100% 以上で張り付く
- VM では steal が高いと「処理が全然進まない」
- 指標
- メモリ
- 指標
- available メモリ
- swap 使用量
- si / so(swap in/out)
- 症状
- SELECT が急に遅くなる(キャッシュ不足)
- UPDATE が固まる(Dirty Page flush 遅延)
- swap 発生 → DB・OS 全体がフリーズ級に重くなる
- 最悪 mysqld が落ちる
- 指標
- ディスク I/O
- 指標
- await … I/O の待ち時間
- util … ディスク使用率(100% は飽和)
- 症状
- UPDATE / INSERT が遅延
- checkpoint が進まず redo log が詰まる
- Dirty Page が全然減らない
- アプリから見ると「API が順番に固まる」状態になる
- 指標
- プロセス負荷(他プロセスの CPU/MEM)
- 指標
- MySQL 以外のプロセスの CPU 使用率
- MySQL 以外のメモリ消費
- 症状
- バックアップ・ログ処理のせいで MySQL が遅くなる
- Java/PHP がメモリを食い尽くし swap 誘発
- 監視エージェントが I/O を独占することもある
- 指標
- ネットワーク
- 指標
- NIC の drop / error
- RTT 遅延(ping)
- DNS 逆引き
- 症状
- “クエリだけが遅い”ように見える(実際はネットワーク)
- DB 接続が遅延する
- DNS 逆引き遅延で mysqld が固まる瞬間が出る
- 指標
まとめ
- MySQL の性能はソフトよりハードと OS に強く依存する
- CPUのシングルスレッド性能、SSDストレージ、十分なメモリが最重要。
業務での活かし方
- パフォーマンス低下の原因調査にあたり
- SQL自体が悪いケースはもちろんあるが、OS/MySQL内部が原因のパターンがあることを認識しておくことで調査の選択肢が増える
- 事象からの原因切り分け
- メモリ負荷→更新系の処理や、キャッシュしきれないほど大量の読み取りが関係
CPU負荷→複雑なSELECTなど、演算処理が関係
- メモリ負荷→更新系の処理や、キャッシュしきれないほど大量の読み取りが関係

コメント