(忙しい人向け)まとめ
- Amazon Aurora MySQL のリードレプリカでは Adaptive Hash Index が有効にならない仕様(バグ?)がある
- この仕様はバージョン 5.6、5.7 両方にあって、たぶん修正され無いと思われる
- パラメーターグループでは有効にすることができるが、実際にMySQLのシステム変数を見ると有効になっていないため見落としがち
- 特定のワークロードでは一部のクエリの実行速度が2倍近く遅くなることもある
経緯
RDS for MySQL で稼働しているシステムを Aurora への移行を検討している中、現状のワークロードから切り出したクエリーを流してベンチマークをとったところ、特定のクエリだけ2倍近く遅くなる事象が発生。
最初は比較的JOINが多いクエリだったので、AuroraとMySQLのクエリオプティマイザの違いからくる問題かと思って、オプティマイザスイッチを変更したりもしたけど改善せず。。
そのとき、たまたまライターに同じクエリを投げたところ、RDS for MySQL と同等の速度になったので、どうやらライターとリードレプリカでは挙動が異なるっぽく、いろいろ調べるとinnodb_adaptive_hash_index
がリードレプリカは無効になっていた。
パラメーターグループの値は無視される
Auroa のパラメーターグループは「パラメータグループ」と「DBクラスターのパラメータグループ」の2種類があり、どちらでも innodb_adaptive_hash_index
の値は変更可能で、どちらを指定してもリードレプリカでは設定が無視されます。
MySQLのコンソールでも変更不可
innodb_adaptive_hash_index
は動的に変更可能なので、MySQL のコンソール上で以下のようなコマンドを実行しても変更できなかった。
mysql> set global innodb_adaptive_hash_index=1;
強制的にフェイルオーバーしてみる
ライターを手動でフェイルオーバーさせてみると、ライターに昇格したインスタンスはinnodb_adaptive_hash_index
が有効になっていて、リードレプリカとして起動した元ライターインスタンスのinnodb_adaptive_hash_index
は無効になっていた。
おそらくリードレプリカとして起動する際に --skip-innodb_adaptive_hash_index
パラメーターが渡されて無効になっているんでしょうね。
この問題はいつから?
以下の stack overflow の回答の中で、2015年8月の AWS forum で既に言及されているものの、今も解消されていないのが確認できる。
そもそも Adaptive Hash Index って?
MySQLではレコードの格納位置を特定するために、B-Tree インデックスが使われます。
この B-Tree インデックスによる計算量は O(log n) です。
これを更に高速化するため、よく検索されるものはMySQLが内部でハッシュインデックスを作成してキャッシュして使うようにしていて、これが Adaptive Hash Index と呼ばれるものです。ハッシュインデックスによる計算量は O(1) で最速です。
ただ、内部的に自動で作られるものなので、ユーザーからコントロールすることもできないし、EXPLAIN
を使っても Adaptive Hash Index が使われているかどうかもわかりません。
また、同時接続が多く、負荷の高いワークロードでは、ハッシュインデックスによる高速化よりもハッシュインデックのデータ更新処理の方に時間がかかったり、特に5.6では単一のスレッドなので、ロック待ちが発生しやすく逆に遅くなったりすることもあります。(5.7では複数スレッドになっているので並列化されいるので問題にはなりにくい)
MySQL :: MySQL 5.6 リファレンスマニュアル :: 14.2.13.6 適応型ハッシュインデックス
Amazon Aurora MySQL が向いているワークロード
Aurora は MySQL の最大5倍のパフォーマンスが出ると書いてありますが、これは sysbench で同時接続数が多い場合です。
sysbench が投げるクエリはJOINも含まないようなかなり軽量なクエリなので、「同時接続数が多く」「軽量なクエリ」を大量に投げるようなワークロードが向いていると言えます。
これは公式のよくある質問にも記載があります。
Amazon Aurora が MySQL よりも優れている領域の 1 つが、ワークロードの同時実行数が非常に多い場合です。Amazon Aurora でワークロードのスループットを最大化するには、多数のクエリやトランザクションを同時実行するようにアプリケーションを作成することをお勧めします。
このことは、先にも触れたように、Adaptive Hash Index は同時接続数が多くて負荷が高いワークロードに向いてないことを考えると真逆の機能と言えます。
とはいえ、Aurora はパフォーマンス以外にも運用面で楽になる機能もたくさんあるため、多少向いてないワークロードでも使いたい。。。