エンジニア必見!Aurora dsqlによるデータベースパフォーマンス最適化術
はじめに:なぜ今、データベースパフォーマンスなのか
現代のアプリケーション開発において、ユーザー体験は成功の鍵を握ります。Webサイトの表示が1秒遅れるだけでコンバージョン率が7%低下するというデータもあるように、システムの応答速度はビジネスに直結する重要な要素です。そして、その応答速度のボトルネックになりやすいのが、システムの心臓部であるデータベースです。
特に、クラウドネイティブ時代のデファクトスタンダードとなりつつあるAmazon Auroraは、その高いパフォーマンスと可用性で多くの開発者に支持されています。しかし、そのポテンシャルを最大限に引き出すためには、データベースの挙動を深く理解し、適切な最適化を施す必要があります。
本記事では、数あるパフォーマンスチューニングのテーマの中でも、特に多くのエンジニアを悩ませる「dsql(Dynamic SQL)」に焦点を当てます。dsqlはアプリケーションの柔軟性を高める強力な武器である一方、一歩間違えれば深刻なパフォーマンス劣化を引き起こす諸刃の剣です。
この記事を読めば、以下の知識を習得できます。
- Amazon Auroraのパフォーマンスに関する基礎知識
- dsqlがパフォーマンス問題を引き起こすメカニズム
- AWSが提供する強力なツール「Performance Insights」などを活用した問題特定方法
- dsqlに起因するパフォーマンス問題を解決するための具体的な最適化テクニック
あなたがもし、「特定の機能だけレスポンスが遅い」「CPU使用率が時々スパイクするが原因がわからない」「開発環境では速いのに本番環境では遅い」といった問題に直面しているなら、この記事はきっとあなたの助けになるはずです。それでは、Auroraとdsqlの奥深い世界へ旅立ちましょう。
第1章:Amazon Auroraのパフォーマンス基礎知識
最適化の話に入る前に、まずAmazon Auroraがなぜ高いパフォーマンスを実現できるのか、そのアーキテクチャの基本を理解しておくことが重要です。
1.1 Auroraアーキテクチャの優位性
従来のモノリシックなデータベースとは異なり、Auroraはコンピュート(DBインスタンス)とストレージを分離したアーキテクチャを採用しています。
- ログ先行書き込み(WAL)の最適化: Auroraの最大の特徴は、ストレージレイヤーにあります。データベースへの変更は、まずREDOログとして記録されますが、Auroraはこのログストリームのみを共有ストレージ(Aurora Storage)に書き込みます。データブロック(ページ)そのものを書き込む必要がないため、書き込みI/Oが大幅に削減され、高いスループットを実現します。
- 共有ストレージアーキテクチャ: データは3つのアベイラビリティーゾーン(AZ)にわたり6重に複製され、高い耐久性と可用性を誇ります。この共有ストレージのおかげで、リードレプリカはプライマリインスタンスとほぼ遅延なくデータを共有でき、読み取り性能のスケーリングが容易です。
- クラスタキャッシュマネジメント: プライマリインスタンスがフェイルオーバーした場合、新しいプライマリ(元レプリカ)は、ウォームアップ期間なしに即座に処理を開始できます。これは、インスタンス間でバッファキャッシュの状態がある程度共有されているためです。
1.2 一般的なデータベースパフォーマンスチューニングの考え方
Auroraは優れたアーキテクチャを持っていますが、データベースチューニングの基本原則は変わりません。パフォーマンス問題は、主に以下のレイヤーで発生します。
- クエリチューニング: 最も効果が高いチューニングです。非効率なクエリを一つ改善するだけで、システム全体のパフォーマンスが劇的に向上することがあります。
EXPLAIN
による実行計画の分析が基本となります。 - インデックス設計: 適切なインデックスは、クエリのパフォーマンスを飛躍的に向上させます。逆に、不適切なインデックスは書き込み性能を劣化させる原因にもなります。
- スキーマ設計: テーブルの構造(正規化・非正規化など)が、クエリの複雑さやパフォーマンスに大きく影響します。
- インスタンスサイジング: CPU、メモリ、ネットワーク帯域など、インスタンスのスペックが不足している場合、スケールアップやスケールアウトが必要です。
- パラメータチューニング: DBパラメータグループを調整することで、メモリ使用量や並列処理など、データベースの挙動を細かく制御できます。
本記事で扱うdsqlの最適化は、主に「1. クエリチューニング」と「2. インデックス設計」に深く関わってきます。
第2章:dsql (Dynamic SQL) とは何か?
dsqlの最適化術を学ぶ前に、まず「dsqlとは何か」「なぜパフォーマンス問題を引き起こしやすいのか」を正確に理解しましょう。
2.1 静的SQLと動的SQL
-
静的SQL (Static SQL):
アプリケーションのコード内に、SQL文全体がハードコーディングされている形式です。実行されるSQLの形が常に同じであるため、データベースは実行計画を効率的にキャッシュし、再利用できます。sql
-- 静的SQLの例
SELECT * FROM users WHERE id = 123; -
動的SQL (Dynamic SQL / dsql):
アプリケーションのロジックやユーザーの入力に応じて、実行時にSQL文が動的に構築される形式です。柔軟性が高い反面、様々な問題を引き起こす可能性があります。“`ruby
動的SQLを生成するRubyコードの例
query = “SELECT * FROM products WHERE ”
conditions = []
conditions << “category_id = #{params[:category_id]}” if params[:category_id].present?
conditions << “price >= #{params[:min_price]}” if params[:min_price].present?
conditions << “price <= #{params[:max_price]}” if params[:max_price].present?query += conditions.join(” AND “)
実行されるSQLの例 (ユーザーの入力によってSQL文の構造が変わる)
// “SELECT * FROM products WHERE category_id = 5 AND price >= 1000”
// “SELECT * FROM products WHERE price <= 5000”
“`
2.2 なぜdsqlはパフォーマンス問題を引き起こしやすいのか?
dsqlの柔軟性は魅力的ですが、以下の理由からパフォーマンスのボトルネックとなりがちです。
-
実行計画の再利用が困難
データベースのオプティマイザは、SQLクエリを受け取ると、最も効率的なデータアクセス方法を計算し、「実行計画」を作成します。この実行計画の作成自体がCPUを消費する比較的重い処理です。静的SQL(厳密にはプリペアドステートメント)の場合、SQLの「形」が同じであれば、パラメータの値が異なっていても、一度作成した実行計画をキャッシュして再利用できます。これにより、オプティマイザの負荷が軽減されます。
一方、dsqlはユーザーの入力によってSQL文の文字列そのものが毎回変化します。
WHERE
句の条件、ORDER BY
の列、SELECT
の列リストなどが変わると、データベースはそれを「新しいクエリ」と認識し、その都度、実行計画をゼロから作成し直さなければなりません。これが高負荷時にCPU使用率を急上昇させる主な原因となります。 -
オプティマイザへの過度な負荷
dsqlは複雑なWHERE
句や多数のJOIN
を生成しがちです。オプティマイザが最適な実行計画を見つけるための計算量は、テーブルや条件の組み合わせによって指数関数的に増加します。非常に複雑なdsqlは、実行計画の作成だけで多くの時間を費やし(パース地獄)、クエリの実行そのものよりも時間がかかってしまうことさえあります。 -
SQLインジェクションのリスク
パフォーマンスとは直接関係ありませんが、dsqlを扱う上で最も注意すべきセキュリティリスクです。ユーザーからの入力を適切にエスケープ処理せずにSQL文に埋め込むと、悪意のあるSQL断片を注入され、データの漏洩や改ざん、破壊につながる可能性があります。これはdsqlを実装する際の絶対的な注意事項です。
第3章:dsqlによるパフォーマンス問題の特定方法
「なんだかシステムが重い」と感じたとき、その原因がdsqlにあるとどうやって突き止めればよいのでしょうか。幸い、AWSは非常に強力な分析ツールを提供しています。
3.1 最強の武器:Performance Insights
Amazon RDS Performance Insightsは、データベースの負荷を視覚的に分析し、パフォーマンスのボトルネックを迅速に特定するためのダッシュボードです。dsql問題の特定において、これほど強力なツールは他にありません。
-
ダッシュボードの概要
Performance Insightsを開くと、まず「DBロード」のグラフが表示されます。このグラフは、データベース内でアクティブなセッション(クエリを実行している、または実行を待っているセッション)の平均数を示しています。DBロードがインスタンスのvCPU数を超えている場合、CPUリソースの競合が発生しており、パフォーマンスが低下している可能性が高いです。 -
DBロードの内訳(凡例)
グラフの棒は色分けされており、何がボトルネックになっているかを示しています。- 緑 (CPU): クエリがCPU上で実行されている時間。dsqlによって実行計画のパースが頻発している場合、この部分が大きくなります。
- 青 (IO:Wait): ディスクI/Oを待っている時間。Auroraでは主にストレージへのREDOログ書き込みなどが該当します。
- その他の色 (Wait Events): ロック待機、バッファ待機など、様々な待機イベントを示します。
-
Top SQLの特定
DBロードグラフの下には、「上位のSQL」というテーブルがあります。これは、指定した期間においてDBロードに最も貢献した(=最も負荷をかけた)SQLクエリのリストです。ここで注目すべきは、正規化されたクエリが表示される点です。dsqlによってリテラル値(例:
id = 123
)が異なっていても、SQLの構造が同じであれば、Performance Insightsはそれらをグルーピングして表示してくれます。dsql問題の兆候:
Top SQLリストに、以下のような特徴を持つクエリが多数表示されている場合、dsqlが問題である可能性が非常に高いです。
*SELECT ... WHERE ... AND ... AND ...
のように、?
(プレースホルダ)が使われておらず、リテラル値がそのまま埋め込まれたクエリが大量に並んでいる。
* 似たような構造だが、WHERE
句の条件の数や組み合わせが微妙に異なるクエリが、それぞれ別の項目としてリストアップされている。
*Executions/min
(毎分の実行回数)が低いにもかかわらず、Load by waits (AAS)
(平均アクティブセッション)が高いクエリ。これは、1回あたりの実行コストが非常に高いことを意味します。 -
実行計画と待機イベントの分析
Top SQLリストから特定のクエリを選択すると、そのクエリの実行計画(EXPLAIN
の結果)や、関連する待機イベントをドリルダウンして分析できます。これにより、「なぜこのクエリが遅いのか?(インデックスが使われていない、など)」「何で待たされているのか?(CPU、I/O、ロックなど)」を詳細に把握できます。
3.2 伝統的だが確実な方法:Slow Query Log
Slow Query Logは、指定した時間(long_query_time
)以上かかったクエリをログに出力する機能です。Performance Insightsがリアルタイムの負荷分析に強いのに対し、こちらは過去に発生した低速クエリを事後分析するのに役立ちます。
-
有効化の方法:
Auroraクラスタのパラメータグループで、slow_query_log
を1
に設定し、long_query_time
に閾値(例:1.0
で1秒)を設定します。 -
分析のポイント:
出力されたログファイルを手動で見るのは大変なので、pt-query-digest
(Percona Toolkit)やmysqldumpslow
といったツールを使って集計・分析するのが一般的です。これらのツールは、dsqlによって生成されたリテラル値の異なるクエリを正規化し、実行回数や合計実行時間順にランキングしてくれます。これにより、最も改善効果の高いクエリを特定できます。
3.3 EXPLAIN
による実行計画の分析
Performance InsightsやSlow Query Logでボトルネックとなっているクエリを特定したら、次はそのクエリがなぜ遅いのかをEXPLAIN
コマンドで解き明かします。
EXPLAIN
は、オプティマイザがどのようにテーブルにアクセスするか(実行計画)を表示するコマンドです。
sql
EXPLAIN SELECT * FROM users WHERE status = 'active' AND last_login_at > '2023-01-01';
見るべき重要なカラムは以下の通りです。
type
: アクセスタイプ。ALL
(フルテーブルスキャン)やindex
(フルインデックススキャン)は改善の余地あり。理想はref
,eq_ref
,range
,const
です。key
: 実際に使用されたインデックス。NULL
の場合はインデックスが使われていません。rows
: スキャンしたおおよその行数。この値が大きいほどコストが高いです。Extra
: 追加情報。Using filesort
(インデックスを使えないソート)やUsing temporary
(一時テーブルの作成)が表示されている場合、クエリやインデックスの設計に問題がある可能性が高いです。
dsqlの場合、アプリケーションログなどから実際に実行されたクエリをコピーし、EXPLAIN
にかけることで、その特定のパターンにおける実行計画を確認できます。
3.4 Aurora Monitoring (CloudWatch Metrics)
補完的な情報として、CloudWatchのメトリクスも監視しましょう。
CPUUtilization
: CPU使用率。dsqlによるパース負荷や非効率なクエリで高騰します。DatabaseConnections
: 接続数。急激な増加は問題の兆候です。SelectLatency
/DMLLatency
: 読み取り/書き込みクエリの平均レイテンシ。BufferCacheHitRatio
: バッファキャッシュのヒット率。低い場合はメモリ不足か、アクセスパターンが非効率(例: フルテーブルスキャン多発)であることを示唆します。
これらのメトリクスを組み合わせることで、いつ、どのような問題が発生しているのかをマクロな視点で把握できます。
第4章:dsqlのパフォーマンスを最適化する具体的な手法
問題の特定ができたら、いよいよ最適化に着手します。dsqlのパフォーマンスを改善するには、いくつかの確立されたアプローチがあります。
4.1 基本中の基本:プリペアドステートメントの活用
dsqlの最大の問題点である「実行計画の再利用が困難」を解決するための最も効果的な方法が、プリペアドステートメント(Prepared Statements)です。
-
プリペアドステートメントとは?
SQL文の「骨格(テンプレート)」と「埋め込む値(パラメータ)」を分離してデータベースに送信する仕組みです。- Prepare: まず、値の部分をプレースホルダ(
?
など)にしたSQLテンプレートをDBに送信し、コンパイルさせます。DBは実行計画を作成し、キャッシュします。 - Execute: 次に、プレースホルダに埋め込む実際の値を送信してクエリを実行します。値が違っても、同じテンプレートであればキャッシュされた実行計画が再利用されるため、パースのオーバーヘッドがありません。
- Prepare: まず、値の部分をプレースホルダ(
-
dsqlからプリペアドステートメントへの書き換え例
変更前(悪いdsqlの例)
“`rubyユーザー入力に応じてSQLを文字列結合で組み立てる
query = “SELECT * FROM products WHERE category_id = #{params[:category_id]}”
results = ActiveRecord::Base.connection.execute(query)
“`変更後(良いプリペアドステートメントの例)
多くの言語やフレームワークでは、プリペアドステートメントが簡単に利用できます。Ruby on Rails (ActiveRecord)
“`rubyプレースホルダを使うだけで自動的にプリペアドステートメントが使われる
products = Product.where(“category_id = ?”, params[:category_id])
“`Java (JDBC)
java
String sql = "SELECT * FROM products WHERE category_id = ?";
try (PreparedStatement pstmt = connection.prepareStatement(sql)) {
pstmt.setInt(1, params.getCategoryId());
ResultSet rs = pstmt.executeQuery();
// ...
}Python (mysql-connector-python)
python
sql = "SELECT * FROM products WHERE category_id = %s"
cursor.execute(sql, (params['category_id'],))
results = cursor.fetchall()
プリペアドステートメントは、実行計画の再利用によるパフォーマンス向上だけでなく、SQLインジェクションを原理的に防ぐことができるため、セキュリティ面でも必須のテクニックです。dsqlを扱う際は、まずプリペアドステートメント化を検討してください。
4.2 アプリケーション側でのクエリの正規化
全てのdsqlをプリペアドステートメントにできないケースもあります。例えば、IN
句の要素数が動的に変わる場合などです。
sql
-- IN句の要素数が1つ
SELECT * FROM users WHERE id IN (1);
-- IN句の要素数が3つ
SELECT * FROM users WHERE id IN (1, 2, 3);
これらはSQLの構造が異なるため、別々のクエリと見なされ、実行計画がキャッシュされません。このような場合、アプリケーション側でIN
句の要素数を固定のバケットに丸める、というテクニックが有効です。
例えば、「要素数を1, 5, 10, 20, 50個のいずれかにパディングする」というロジックを実装します。要素数が3個の場合は5個用のクエリテンプレートを使い、残りはNULL
や未使用のIDで埋めます。これにより、生成されるSQLのバリエーションを大幅に減らし、実行計画の再利用率を高めることができます。
4.3 dsqlを前提としたインデックス設計
dsqlは様々な条件でテーブルにアクセスするため、インデックス設計が非常に重要になります。
-
複合インデックスの活用:
dsqlのWHERE
句で頻繁に組み合わせて使われるカラムは、複合インデックスを作成することで効果的にパフォーマンスを改善できます。例えば、WHERE category_id = ? AND status = ? ORDER BY created_at DESC
というクエリが頻出する場合、(category_id, status, created_at)
という複合インデックスが非常に有効です。インデックス内の列の順序も重要で、一般的にはカーディナリティ(値のばらつき)が高い列を前に置くと効率が良くなります。Performance InsightsやSlow Query Logで頻出するクエリパターンを分析し、最適なインデックスを設計しましょう。 -
カバリングインデックス:
クエリが必要とする全てのカラムがインデックスに含まれている場合、データベースはテーブル本体にアクセスすることなく、インデックスだけで結果を返すことができます。これをカバリングインデックスと呼びます。dsqlでSELECT
句の列が固定されている場合、カバリングインデックスは劇的な効果を発揮します。EXPLAIN
のExtra
にUsing index
と表示されれば、カバリングインデックスが使われています。
4.4 スキーマ設計の見直し
時には、dsqlが複雑化している原因が、データベースのスキーマ設計そのものにある場合があります。例えば、柔軟性を重視しすぎたEAV(Entity-Attribute-Value)モデルは、非常に複雑なdsqlを生成しがちです。
パフォーマンス問題が深刻な場合は、dsqlを単純化できるよう、サマリーテーブルを導入したり、非正規化を行ったりするなど、スキーマ設計の見直しを検討する価値があります。これは大きな変更になりますが、根本的な解決につながる可能性があります。
4.5 Aurora特有の機能を活用した最適化
-
リーダーインスタンスへのクエリオフロード:
dsqlによって生成されるクエリが参照系(SELECT
)である場合、その負荷をプライマリインスタンスからリードレプリカ(リーダーインスタンス)にオフロードできます。Auroraでは、クラスタエンドポイント(書き込み用)とリーダーエンドポイント(読み取り用)が提供されています。アプリケーション側でクエリの種類に応じて接続先を振り分けることで、プライマリインスタンスの負荷を軽減し、システム全体の書き込み性能と読み取り性能を両立させることができます。 -
クエリプラン管理 (Query Plan Management – QPM) for Aurora PostgreSQL:
Aurora PostgreSQLには、オプティマイザが選択した実行計画を検証し、承認済みの計画のみを使用させる「クエリプラン管理(QPM)」という機能があります。データベースの統計情報が変化したことなどにより、オプティマイザが突然非効率な実行計画を選択してしまう「実行計画の退行」を防ぐのに非常に有効です。dsqlによって実行計画が不安定になりがちな場合に、パフォーマンスを安定させるための強力な武器となります。
4.6 最終手段:オプティマイザヒントの利用
どうしてもオプティマイザが期待通りの実行計画を選択してくれない場合の最終手段として、オプティマイザヒントがあります。これは、SQL文の中に「このインデックスを使ってほしい(USE INDEX
)」といった指示を直接書き込む方法です。
sql
SELECT * FROM users USE INDEX(idx_status_logindate) WHERE status = 'active' AND last_login_at > '2023-01-01';
ただし、ヒント句は諸刃の剣です。
* 特定の実行計画に縛られるため、データ分布の変化に対応できなくなる。
* データベースのバージョンアップで挙動が変わる可能性がある。
* コードの可読性とメンテナンス性を著しく低下させる。
利用は慎重に、限定的に行うべきです。
第5章:実践的なケーススタディ
理論だけではイメージが湧きにくいかもしれません。ここでは、よくある2つのシナリオを例に、問題解決のプロセスを見ていきましょう。
ケーススタディ1:ECサイトの多機能検索
-
問題:
ECサイトの商品検索ページで、カテゴリ、価格帯、ブランド、在庫の有無など、複数の条件を組み合わせて検索できる。ユーザーがチェックボックスをオン/オフするたびにdsqlが生成され、特定の組み合わせで検索がタイムアウトすることがある。CloudWatchを見ると、検索リクエストが増えるとCPU使用率が100%に張り付く。 -
特定プロセス:
- Performance Insights を確認。DBロードのほとんどが緑色(CPU)で占められている。
- Top SQL リストを見ると、
SELECT * FROM products WHERE ...
という構造のクエリが、WHERE
句の条件の組み合わせパターンごとに別々のクエリとして大量にランクインしている。Executions/min
は低いが、Load by waits
は高い。 - 特定の遅いクエリを
EXPLAIN
にかけると、type
がALL
(フルテーブルスキャン)になっており、適切なインデックスが使われていないことが判明。
-
最適化アプローチ:
- インデックスの追加: 検索条件で頻繁に使われる
category_id
,brand_id
,status
を組み合わせた複合インデックス(category_id, brand_id, status)
を作成。 - プリペアドステートメント化: アプリケーションコードを修正。検索条件の値をプレースホルダで渡すように変更し、SQLテンプレートのバリエーションを減らす。価格帯(
price >= ? AND price <= ?
)のような範囲検索もプレースホルダ化する。 - リーダーインスタンスへのオフロード: 商品検索は参照系クエリなので、アプリケーションのDB接続設定を更新し、検索クエリがリーダーエンドポイントに向かうように変更。これにより、プライマリインスタンスの負荷を劇的に削減。
- インデックスの追加: 検索条件で頻繁に使われる
ケーススタディ2:BIダッシュボードの表示
-
問題:
管理画面のBIダッシュボードで、ユーザーが表示する指標(売上、ユーザー数など)や、ソート順(日付順、金額順など)を自由にカスタマイズできる。データ量が増えるにつれて、ダッシュボードの表示がどんどん遅くなってきた。 -
特定プロセス:
- Slow Query Log を有効化し、
pt-query-digest
で分析。SELECT ... FROM sales_logs ... GROUP BY ... ORDER BY ...
というクエリがワーストランキング上位を占めている。 - ログの詳細を見ると、
ORDER BY
句やGROUP BY
句がユーザーの選択によって動的に変わっている。 EXPLAIN
をかけると、多くのパターンでExtra
にUsing temporary; Using filesort
が表示されている。これは、インデックスを使ってソートできず、ディスク上で一時テーブルを作成してソートしていることを意味し、非常に遅い処理。
- Slow Query Log を有効化し、
-
最適化アプローチ:
- ソート用インデックスの追加:
ORDER BY
で指定される可能性のあるカラム(例:sales_date
,amount
)を含む複合インデックスを作成。 - サマリーテーブルの導入: ダッシュボードで必要な集計結果(日別売上、カテゴリ別売上など)を、夜間バッチで事前に計算し、別の「サマリーテーブル」に保存しておく。ダッシュボードは、巨大な生データではなく、この軽量なサマリーテーブルを参照するように変更。これにより、表示のたびに行う高負荷な集計処理が不要になる。
- UI/UXの見直し: アプリケーション側で、選択可能なソート順や指標の組み合わせを、パフォーマンスが担保できるパターンに敢えて制限することも検討。無限の自由度とパフォーマンスはトレードオフの関係にある。
- ソート用インデックスの追加:
まとめ:dsqlを飼いならし、パフォーマンスを最大化する
本記事では、Amazon Auroraにおけるdsqlのパフォーマンス最適化術について、その原因、特定方法、そして具体的な解決策までを詳細に解説してきました。
dsqlは、アプリケーションに柔軟性をもたらす強力な機能ですが、その裏にはパフォーマンス劣化という大きなリスクが潜んでいます。重要なのは、dsqlを闇雲に恐れて避けるのではなく、その特性を正しく理解し、「飼いならす」ことです。
最後に、重要なポイントをもう一度振り返りましょう。
- 問題の可視化が第一歩: Performance Insightsは、dsql問題を特定するための最も強力なツールです。DBロードとTop SQLを常に監視する習慣をつけましょう。
- プリペアドステートメントは銀の弾丸: dsqlの最適化は、まずプリペアドステートメント化から検討してください。パフォーマンスとセキュリティの両面で絶大な効果があります。
- インデックスはdsqlを支える土台: dsqlで使われるアクセスパターンを予測し、効果的な複合インデックスやカバリングインデックスを設計することが不可欠です。
- アーキテクチャで解決する: クエリ単体のチューニングだけでなく、リーダーインスタンスへのオフロードやサマリーテーブルの導入など、アーキテクチャレベルでの最適化も常に視野に入れましょう。
- 継続的な改善を: データベースのパフォーマンスチューニングに終わりはありません。アプリケーションの成長やデータ量の増加に伴い、新たなボトルネックが必ず生まれます。定期的なモニタリングと改善を文化として根付かせることが、安定したサービス提供の鍵となります。
Amazon Auroraという強力なデータベースのポテンシャルを最大限に引き出し、ユーザーに快適なサービスを届け続けるために、本記事で得た知識があなたのエンジニアリングの一助となれば幸いです。