運用してわかった Amazon RDS のパフォーマンスを上げる 3 つのコツ
Posted on
本番環境で RDS を運用して数ヶ月。いろいろ試して RDS のパフォーマンスを上げるコツがわかってきたのでまとめたいと思います。
ここで取り上げるコツは以下を前提にしています。
- データベースは PostgreSQL (Multi-AZ 配置)
- Read よりも Write が多い
- 夜間のバッチ処理がピーク
- 1 レコードは小さいが、一度に書き込むレコード数は多い
アプリケーションの特性によっては当てはまらないこともあるでしょうし、他の RDBMS では結果が違ってくると思います。そこを踏まえたうえで参考にしてください。
Availability Zone はどちらかに寄せる
RDS の Multi-AZ は耐障害性を上げるために欠かせない機能で、本番環境では Multi-AZ 配置が推奨されています。
Multi-AZ 配置にすると物理的に独立した AZ (Availability Zone) 間でデータを同期してくれます。「RDS for PostgreSQL で UNLOGGED テーブルを試してみる」にも書きましたが、この同期はディスクレベルで行われています。
いいこと尽くめに思えますが、唯一の欠点が AZ 間のレイテンシです。 Multi-AZ 配置にすると AZ 間の通信が発生してしまうので、どうしてもパフォーマンスが落ちてしまいます。特に、アプリケーションサーバが AZ をまたいで RDS に書き込むと、ログ上ではっきりと差がわかるくらいパフォーマンスが落ちます。
これを避けるには、アプリケーションサーバと RDS のマスターを同じ AZ に置きます。 RDS のマスターが ap-northeast-1c にあるなら、EC2 インスタンスも ap-northeast-1c に置くということです。
ひとつの AZ に寄せるのは AWS のインフラ設計としてはアンチパターンです。 ですが、リトライ可能なバッチ処理など場合によってはひとつの AZ に寄せてパフォーマンスを優先するのもアリだと思います。アプリケーションに求められる要件と相談して決めましょう。
BULK INSERT を活用する
RDS のサイトにも書いてあるように、Multi-AZ は同期レプリケーションです。非同期レプリケーションではありません。
MySQL、Oracle、および PostgreSQL エンジンのマルチ AZ 配置は、同期物理レプリケーションを活用して、スタンバイしているデータをプライマリに合わせて最新の状態に維持します。
マスタのディスクに書き込みが発生すると AZ をまたいでスレーブにも同期されます。書き込みリクエストはスレーブに反映されるまで待たされます。先ほども書いたとおり AZ をまたぐとレイテンシが発生します。普段は気にする必要はありませんが、一時的に書き込み性能を求められるときはこのレイテンシが問題になってきます。塵も積もれば山となるのです。
そこで活用したいのが BULK INSERT です。たとえば 100 レコードを書き込む場合、1 回ずつ INSERT して 100 回リクエストを投げるのではなく、BULK INSERT で 1 回のリクエストにまとめてしまいます。こうすれば AZ 間の通信を大きく減らせます。「チマチマやっとらんと、ドサッと入れんかい!」です。
自分が担当しているプロダクトでは、BULK INSERT に変えたことで RDS への書き込みが数倍も改善しました。
Provisioned IOPS に適した環境にする
Provisioned IOPS (PIOPS) を設定すればストレージの IOPS を指定できますが、やみくもに高い値にしてもパフォーマンスは伸びません。 PIOPS のパフォーマンスを最大限に引き出すには RDS と EC2 にそれぞれ工夫が必要です。
RDS のデータは EC2 と同じように EBS ボリュームに保存されています。 EBS はネットワーク経由で読み書きしますが、アプリケーションサーバと EBS の通信が同じネットワークだと互いに帯域を食い合ってしまい、期待する IOPS に達する前に頭打ちになります。
これを避けるには「PIOPS 用に最適化」されたインスタンスタイプを選びます。 M3 世代だと db.m3.xlarge 以上、R3 世代だと db.r3.xlarge 以上です。これらのインスタンスで PIOPS を指定した場合、EBS のネットワークを専用に確保してくれます。ネットワークが別になることで、高速かつ安定した I/O が実現します。
これは EC2 にも当てはまります。アプリケーションサーバには EBS 最適化インスタンスを選び、必要であれば PIOPS を指定しましょう。オプションの名前は違いますが、理屈は RDS と同じです。
AWS マイスターシリーズのスライドに図解でわかりやすく解説されています。
まとめ
ここまで読むと、これまでやってきたパフォーマンスチューニングと変わりないことがわかると思います。
- ノード間の通信を極力減らし、レイテンシの影響を最小化する
- SQL を最適化する
- ネットワークのボトルネックを把握する
AWS はソフトウェアのように柔軟に扱えるので物理的なレイヤーを意識することはありませんが、それぞれのサービスがどういう仕組みになっているのか知っておくことは大切です。
よい AWS ライフを!