免責事項
この記事はMorgan Tocker氏によるMySQL Server Blogの投稿「MySQL 8.0: Retiring Support for the Query Cache」(2017/5/30)をユーザが翻訳したものであり、Oracle公式の文書ではありません。
MySQLのクエリーキャッシュはパフォーマンスを改善するためにあるが、それは重大なスケーラビリティー上の問題を抱えていて、深刻なボトルネックに簡単になってしまいかねない。
これは、MySQLチーム内でも確かに長い間言われてきたことです。今日の記事の本題に入る前に、少しイントロダクションを書かせてください。
クエリーキャッシュ入門
MySQLのクエリーキャッシュとは、クエリーの結果のキャッシュです。 SEL
から始まる受け取ったクエリーをハッシュテーブルと比較し、一致するものがあれば、クエリーの過去の実行時の結果を返します。これにはいくつかの制限事項があります。
- クエリーはバイト単位で一致している必要があります(クエリーキャッシュはパースをしません)。
- 非決定的な機能を使うと、クエリーはキャッシュされません(一時テーブルやユーザー変数、
RAND()
、NOW()
、UDFを含みます)。 - クエリーキャッシュは有効期限切れの結果を返さないように設計されています。テーブルに対するどんな変更も、そのテーブルに関するキャッシュを無効化します。
- InnoDBでキャッシュを使う時にはいくつかの制限があります(MVCCを守るためです。トランザクションを開いたら、「キャッシュ」はあなたが得たいビューのデータを表してはいないでしょう)。
最適な使用シナリオ
数年前に私の個人ブログに、以下のように書きました。
クエリーキャッシュの理想的な使用例は、何百万行もスキャンするのに数行しか返さないような非常に重いクエリがたくさんあり、かつほとんど読み出し専用という場合です。例えば、Webページのフォームに必ず表示されるドロップダウンリスト内の値を生成する複雑なクエリのようなものがあり得るでしょう。このような状況では、インデックスが足りないことから来るパフォーマンス問題を、クエリーキャッシュが隠してくれて、(MySQLの)初心者ユーザーを助けてくれます。
このコメントは今でも正しいですが、アプリケーションに干渉しないようにするためのDBA用のツールも改善されてきているということを指摘しておくのも重要だと思うのです。
MySQLサーバーには、今ではヒントを入れることでクエリーを書き換える機能(あるいはパフォーマンス改善のための他の変更)もあります。また、中間に置いてクエリーキャッシュをするProxySQLのようなサードパーティーのツールもあります。ProxySQLは、上で挙げたような例(ドロップダウンの値のリストを作る)でもうまく動く、キャッシュに対するTTLもサポートしています。
クエリーキャッシュの限界
クエリーキャッシュは、マルチコアマシンでの高スループットな負荷に対してスケールしないことが知られていて、MySQL 5.6 (2013年)からはデフォルトで無効化されています。Reneはこれを昨日の記事でも追認していますが、過去にはStewart Smith氏やDomas Mituzas氏からも指摘されています。
スケーラビリティーに関しては改善され得ると考えても、キャッシュにヒットするクエリーの性能しか改善されないので、クエリーキャッシュの制限になる要素は、パフォーマンスの予測可能性が改善されない点になります。ユーザーがアクセスするシステムでは、ピークのスループットを改善するよりも、パフォーマンスのばらつきを小さくすることが重要であることがよくあります。
A Top-Down Approach to Achieving Performance Predictability in Database Systemsのスライド 2/47
(訳注 : 生のパフォーマンスに焦点を当てすぎると、パフォーマンスの予測可能性を無視しすぎることになることを示したスライド)
A Top-Down Approach to Achieving Performance Predictability in Database Systemsのスライド 3/47
(訳注 : レイテンシーが重要性を持つアプリケーションや、インタラクティブなアプリケーションは、パフォーマンスの予測可能性が重要であることを示したスライド)
クエリーキャッシュのサポートをやめるという決断
ミシガン大学アナーバー校のJiamin Huang 、 Barzan Mozafari 、 Grant Schoenebeck 、 Thomas F. Wenischらによる研究結果と、私たちも同意見です。私たちは、クエリーキャッシュに対する改善と、全てのワークロードに対して改善がみられるような最適化を対比させてみました。
これらの選択肢は直交するものではありますが、エンジニアリングリソースは限られています。つまり、私たちはより一般的に全てのワークロードに適用できる改善に投資するよう戦略転換しているのです。
私たちは、キャッシュはクライアントに近いところに移動すると最大の利益が得られる、というReneの結論にも賛成です。
"Client + 2x ProxySQL"のグラフがキャッシュをクライアントに移動した時に5.2倍のパフォーマンスになっていることを表しています
既存ユーザーのアップグレードパス
既存の制限はありますが、クエリーキャッシュはMySQL 5.7のライフタイムの間はサポートが続けられます。MySQL 8.0ではクエリーキャッシュはサポートされず、アップグレードするユーザーは、サーバーサイドのQuery Rewriteや、中間に置いてキャッシュに使うProxySQLのどちらかを使うことが推奨されることになるでしょう。
この変更によって影響を受けるのは少数のユーザーのみだと予測していますが、もし気になるようなら、連絡を取ってください!
MySQLを使ってくれてありがとう!