MySQL 5.7 から 8.0 への移行で性能劣化が発生する原因と対策
はじめに
MySQL 5.7から8.0にアップグレードすると、特定のシステム環境において性能が劣化することがあります。特に、MySQL 8.0はスケーラビリティ向上を目指した大きな変更が加えられていますが、その一方で、単発クエリや小規模セッションでの性能低下が報告されています。今回は、性能劣化の主な原因と対策について解説します。
性能劣化の原因
- クエリキャッシュの廃止
MySQL 8.0では、スケーラビリティ向上のためにクエリキャッシュが廃止されました。
クエリキャッシュは、同じクエリを繰り返し実行する場合に効率的ですが、スケーラビリティを目指す際にキャッシュが逆にボトルネックになっていました。
特に MySQL のクエリキャッシュでは、複数のコアが並行して動作する環境でのキャッシュの同期に問題が生じ、パフォーマンスが低下します。
そのため、MySQL側はキャッシュの管理をデータベースから外し、クライアントやアプリケーションレベルでキャッシュを管理する方針にシフトしました。
この設計により、データベース自体はスケーラブルな構成を維持しつつ、キャッシュの同期問題を回避できるようになっています。
- ログシステムの刷新
MySQL 8.0ではログシステムが大幅に刷新され、数百セッション以上を扱う場合の性能が向上しています。しかし、セッション数が100未満の場合、逆に性能が低下することがあります。この変更は、大規模なシステムにおいてスケーラビリティを優先するために導入されたものです。
- Materializationの動作変更
MySQL 8.0では、非相関サブクエリを相関サブクエリに書き換える動作が廃止され、代わりにMaterializationがデフォルトで使用されるようになりました。この変更により、特定のクエリで性能が低下することがあります。特に、大量のデータを扱うクエリでは、Materializationの動作がボトルネックになることがあります。
性能改善のための対策
- Materializationを無効化
Materializationによる性能劣化が疑われる場合、materialization=off
に設定することで、クエリのパフォーマンスを改善できる可能性があります。特に、MySQL 5.7から移行した環境では、この設定を無効化して改善が見られることが多いです。
- ハッシュ結合の有効化
MySQL 8.0では、ハッシュ結合が新たに導入され、block_nested_loop=on
に設定することで、BNL(Block Nested Loop)の代わりにハッシュ結合を使用できます。join_buffer_size
を増やすことで、結合処理のパフォーマンスが向上します。デフォルトの256KBでは不十分な場合があるため、4MB程度に設定することが推奨されます。
- インスタンスクラスのアップグレード
もしCPUやメモリが不足している場合、DBインスタンスのクラスを上げることも一つの手です。例えば、db.m5.xlarge
から db.m5.2xlarge
へアップグレードすることで、短期的な性能改善が期待できます。ただし、クラスを上げるだけでは解決しない場合もあり、パラメータ調整が必要です。
今後の取り組み
MySQL 5.7から8.0への移行は、特に大規模なシステムでスケーラビリティ向上を目指すための変更が多く含まれています。しかし、小規模なシステムや単発クエリを多用する環境では、性能劣化が発生することがあります。クエリキャッシュの廃止やMaterializationの動作変更など、MySQL 8.0の新しい仕様に対応するためには、適切なパラメータ調整やクエリの最適化が必要です。
クエリログやメトリクスをしっかりと確認し、性能改善に向けた対策を講じていくことが重要です。特に、optimizer_switch
の設定やMaterializationの無効化などのパラメータ調整が、パフォーマンスの鍵を握るケースが多いです。
まとめ
MySQL 5.7から8.0への移行は、多くの改善点がある一方で、特定の環境では性能劣化が発生することがあります。クエリキャッシュの廃止、ログシステムの変更、Materializationの影響などが主な要因です。これらの問題に対応するためには、パラメータの調整やクエリの最適化が必要です。今後も、性能改善に向けたベストプラクティスを取り入れながら、MySQL 8.0の環境を最適化していくことが求められます。
Discussion