RDSの遅さとコストを同時に改善する進め方
「RDSが遅くなるたびにインスタンスクラスを一段上げてしのいできたが、気づけば費用が当初の3倍になっていた」——既存プロダクトの改善相談で、驚くほどよく聞く話です。サービスが重いという声が上がるたびに db.t3.medium を db.r5.large に、それでも足りずさらに上のクラスに、という対応を繰り返した結果、月々のRDS費用だけで数十万円を払い続けている、というケースも珍しくありません。
厄介なのは、この対応がその場では確実に効くことです。インスタンスを上げればCPUにもメモリにも余裕ができ、体感の遅さは一時的に解消します。しかし根本原因のクエリやスキーマがそのままなら、データが増えるにつれて再び同じ壁にぶつかり、また一段上げる——この繰り返しがコストを際限なく押し上げていきます。この記事では、スケールアップに頼る前にやるべき改善と、性能とコストを両立させる進め方を、発注者向けに整理します。
なぜ「とりあえずスケールアップ」が起きるのか
技術的な理由は単純です。インスタンスクラスの変更はコンソールから数クリックで実行でき、数分〜数十分のダウンタイムを経れば確実に効果が出ます。一方でスロークエリの調査やインデックス設計は、原因特定に時間がかかり、担当者のスキルにも左右されます。「早く直したい」というプレッシャーの前では、即効性のある選択肢が選ばれやすいのは自然なことです。
ただし、これは応急処置であって根本解決ではありません。非効率なクエリやインデックス不足はインスタンスを大きくしても消えません。むしろ「スペックで隠れているだけ」の状態が続き、次にデータ量が倍になったタイミングで同じ問題が再発します。スケールアップは「時間を買う」施策であり、買った時間で根本原因を直すのが本来の使い方です。
スケールアップの前にやること
インスタンスを上げる前に、私たちは必ず次の順番で確認します。
1. スロークエリの特定と改善
まずPostgreSQLなら log_min_duration_statement、MySQLなら slow_query_log を有効にし、実際にどのクエリが遅いかを数値で特定します。「体感で重い」という状態から「このクエリが実行回数×平均時間で最も負荷をかけている」という状態に変えるだけで、打ち手の解像度が大きく上がります。
EXPLAIN ANALYZEで実行計画を確認し、Seq Scan(順次スキャン)が大きなテーブルに発生していないかを見る- WHERE句・JOIN条件・ORDER BYに使われているカラムに、必要なインデックスが張られているかを確認する
- 逆に使われていないインデックスが書き込み負荷を上げていないかも合わせて見る
インデックス不足によるフルスキャンは、CPU使用率を押し上げる最も典型的な原因です。ここを直さずにインスタンスを大きくすると、単に「フルスキャンをより高いスペックで力任せに処理している」だけの状態になります。DBボトルネックの原因特定と改善手順はDBボトルネックで遅いWebサービスの改善手順で詳しく解説しています。
2. 接続数とコネクションプールの見直し
RDSが「重い」と感じる原因が、実はCPU負荷ではなく接続数の枯渇だったというケースもよくあります。
- Webサーバーのワーカー数・スレッド数に対して、RDSの
max_connectionsが不足していないか - Rails標準のコネクションプールやPgBouncerのようなプーラーが適切なサイズで設定されているか
- 長時間居座る不要なトランザクションが接続を掴んだまま解放していないか
接続数の枯渇はインスタンスクラスを上げても直接は解消しません(上位クラスほど max_connections の上限は上がりますが、根本原因である接続の使い方が悪ければ再び枯渇します)。プーラーの導入や設定見直しのほうが、費用をかけずに効果が出る領域です。
インスタンスクラスの適正化(上げるだけでなく下げる余地も見る)
スケールアップを繰り返してきたプロダクトほど、実は現在のインスタンスクラスが過大というケースが多く見られます。
- CloudWatchでCPU使用率・メモリ使用率(FreeableMemory)・接続数の実測データを直近1〜3ヶ月分確認する
- ピーク時でもCPU使用率が慢性的に低い(例えば平常時20%未満)なら、ダウンサイジングの余地がある
- 逆に慢性的に高止まりしているなら、クエリ改善を先に行った上で、それでも不足する分だけスペックを上げる
ここで重要なのは、ダウンサイジングは負荷検証を挟んでから段階的に行うことです。いきなり一段下げていきなり障害を招くのではなく、まずステージング環境や低トラフィックの時間帯で様子を見ながら進めます。また、世代の新しいインスタンスタイプ(例えば旧世代の db.m4 から db.m6i へ)に切り替えるだけで、同等以下の料金でCPU性能が上がることもあり、クラスを下げずにコストを下げられる場合もあります。
リードレプリカという選択肢
書き込みは少ないが読み取りが多い(管理画面、レポート機能、検索、参照系API)というプロダクトでは、プライマリのインスタンスクラスを上げる前にリードレプリカの導入を検討する価値があります。
- 参照系のクエリをレプリカに逃がすことで、プライマリのCPU・接続数の余裕が生まれる
- レプリケーションラグ(数百ミリ秒〜数秒程度の遅延)が許容できる箇所から段階的に移行するのが安全
- 結果として、プライマリを大きくする代わりに、比較的安価なレプリカを追加するほうが総コストを抑えられることがある
ただし、レプリカはインスタンス台数が増える分だけ固定費も増えるため、「読み取り負荷が本当にボトルネックか」をCloudWatchの指標で確認してから導入するのが順番として正しいアプローチです。
性能とコストを両立させる考え方
ここまでの打ち手を踏まえると、性能改善とコスト削減は対立する目標ではなく、同じ診断から生まれる両輪だと分かります。
- クエリとインデックスを改善すれば、同じインスタンスクラスでもレスポンスが速くなる(性能改善)
- 同時に、無駄なCPU消費が減るため、ダウンサイジングの余地が生まれる(コスト削減)
- リードレプリカの導入は、プライマリの負荷を下げつつ、参照系の応答速度も上げる
逆に言えば、原因を特定せずインスタンスクラスだけを上げ続けるのは、性能面でも「その場しのぎ」であり、コスト面でも「無駄な固定費の積み上がり」という、両方にとって最も分の悪い選択です。私たちが改善に入るときは、まずCloudWatchの指標とスロークエリログから現状を可視化し、「性能を落とさずに下げられる部分」と「性能のために上げるべき部分」を切り分けてから、変更の順序を計画します。RDSを含むAWSインフラ全体のコスト診断については既存プロダクトのAWSコストを診断する観点と削減の優先順位もあわせてご覧ください。
外注する場合に確認すべきこと
RDSのパフォーマンスとコストの改善を外部チームに依頼する際は、次の点を確認しておくと安心です。
- いきなりインスタンスクラスの変更を提案してこないか: スロークエリログとEXPLAINでの原因特定、CloudWatch指標の確認を先に行う計画になっているか
- 性能とコストを別々の担当・別々の提案として扱っていないか: 両方を同じ診断から一体で見ているか
- 変更を段階的に検証する手順があるか: ダウンサイジングやレプリカ移行を、負荷試験や低トラフィック帯での検証を挟んで進める計画か
- 改善前後の数値(レスポンスタイム・費用)を比較できるか: 体感ではなく数値で効果を示せるか
技術面の詳細はインフラの技術ページに、進め方全体はモダナイゼーション支援サービスにまとめています。
まとめ
- RDSが遅いからと場当たり的にインスタンスクラスを上げ続けると、根本原因のクエリやスキーマは直らないままコストだけが積み上がる
- スケールアップの前に、スロークエリ改善・インデックス見直し・接続数とプーラーの設定確認を行い、現在のインスタンスクラスが実測データに対して過大でないかも見る
- 性能改善とコスト削減は対立する目標ではなく、同じ診断(CloudWatch指標・スロークエリログ)から両方の打ち手が見つかる
「スケールアップを繰り返しているのに費用ばかり増えている」という段階でもご相談いただけます。torcheees では既存プロダクト改善の診断と、継続的な改善支援を提供しています。まずはお問い合わせフォームから現状の構成と費用感を聞かせてください。