オプティマイザはMySQLのバージョンごとに別物
MySQLをバージョンアップしたら、アプリは動いているのに急に遅くなった。
SQLもインデックスも変えていないのに、特定の画面だけ数十秒かかる。
この現象、実は珍しくありません。
そして原因の多くは、ストレージでもCPUでもありません。
オプティマイザが変わったことです。
MySQLはバージョンごとに機能が追加されますが、最も影響が大きいのはSQL機能ではなく「実行計画を決めるアルゴリズム」です。
つまりMySQLのバージョンアップとは、別のデータベースに近い挙動の変化を含みます。
オプティマイザとは何をしているのか
MySQLのオプティマイザ(optimizer)は、SQLをどう実行するかを決める頭脳です。
SQLは「何を取得したいか」しか書いていません。
SELECT * FROM orders WHERE created_at >= '2025-01-01';
このときMySQLは次を判断します。
- どのインデックスを使うか
- フルスキャンするか
- JOIN順序はどうするか
- 一時テーブルを使うか
- ソート方法は何か
つまりSQLの性能は、SQL文そのものよりオプティマイザの判断に依存します。
バージョンごとに何が変わるのか
MySQLのアップデートでは、オプティマイザが継続的に改良されています。
ここが重要です。
多くの人は「速くなる」と考えます。
しかし実際は「判断基準が変わる」です。
例えば以下の変更が行われてきました。
- 統計情報の扱い
- インデックス選択のコスト計算
- JOIN順序の探索方法
- サブクエリの最適化
- 派生テーブルの扱い
- Hash Join の導入(8.0系)
つまり同じSQLでも、選択される実行計画が別物になります。
実際に起きる典型的な問題
もっとも多いのは「遅くなった」です。
例としてJOINを見ます。
SELECT * FROM users u JOIN orders o ON u.id = o.user_id WHERE u.status = 'active';
あるバージョンでは users を先に絞り込み、少数の行に対して orders を参照します。
しかし別のバージョンでは orders を先に読み、そこから users を参照する計画を選ぶことがあります。
SQLは同じでも、読み込む行数が100倍以上変わります。
結果として、アプリ側から見ると「突然遅くなった」ように見えます。
これはバグではありません。
オプティマイザの「より正しい推定」の結果です。
なぜ開発環境では起きないのか
ここがさらに厄介です。
開発環境では再現しないことが多いです。
理由は単純で、データ量と分布が違うからです。
- 開発環境:件数が少ない、均一
- 本番環境:件数が多い、偏りがある
オプティマイザは統計情報からコストを計算します。
本番の分布では誤差が大きくなり、別の実行計画が選ばれます。
そのため、バージョンアップ後に本番だけ遅くなります。
バージョンアップ時の危険な思い込み
よくある思い込みがあります。
「テストが通ったから大丈夫」
これは機能テストの話です。
オプティマイザの問題は機能ではなく性能です。
しかも、全SQLを網羅的に検証するのは現実的ではありません。
実際には、運用後に初めて問題のSQLが使われて発覚します。
対策:必ず見るべきもの
バージョンアップ時に重要なのは、アプリの画面ではありません。
実行計画の差分です。
最低限、重要なクエリで確認します。
EXPLAIN FORMAT=JSON SELECT ...;
旧バージョンと新バージョンで
- 使用インデックス
- 予測行数
- JOIN順序
が変わっていないかを確認します。
ここを見ずに本番移行すると、リリース後に性能障害として発覚します。
ヒント固定は最終手段
遅くなったSQLに対し、インデックスヒントを入れて固定することがあります。
SELECT /*+ INDEX(users idx_status) */ * FROM users WHERE status = 'active';
これは有効なこともあります。
しかし注意点があります。
データ分布が変わると、そのヒントが最適でなくなる可能性があります。
また次のバージョンで逆効果になる場合もあります。
ヒントは恒久対策ではなく、回避策です。
バージョンアップの現実的な向き合い方
MySQLのバージョンアップは、アプリの互換性よりもオプティマイザ互換性の問題が大きいです。
SQLが動くかどうかではなく、
「同じ速さで動くか」を確認する必要があります。
性能問題はリリース直後には気づきにくく、アクセス増加後に顕在化します。
そのため、バージョンアップの検証では成功条件を「エラーが出ない」にしない方が安全です。
MySQLは単なる保存エンジンではありません。
実行計画を選択する判断システムです。
そしてバージョンが変わるということは、その判断基準が変わるという意味です。
アップデートとは、機能追加よりも「考え方の変更」に近い作業だと理解すると、トラブルの予測がしやすくなります。