📖

RDS の Optimized Reads

に公開

RDS Optimized Reads とは?

「RDS Optimized Reads(最適化された読み取り)」とは、Amazon RDS(Relational Database Service) において読み取りパフォーマンスを向上させるための機能です。これは、特に 読み取りが多いワークロード に対して効果的で、RDS インスタンスが NVMe(SSDを使用したストレージデバイスとホストコンピュータの間で高速にやり取りするための通信プロトコル)ベースのローカルインスタンスストレージ を利用して、データ読み取りのスループットとレイテンシを大幅に改善します。

通常、RDSはデータを保存・読み書きするのに「EBS」という外部ストレージを使います。これは安全で便利なのですが、読み書き速度があまり速くないことがあります。
RDSの中でも、特定のインスタンスタイプ(例:db.m5d, db.m6gdなど)を使うと、「インスタンスストア」 という、そのサーバーに直接ついてる超高速なSSD(NVMe) が使えるようになります。

このSSDは、下記のような特徴があります。

  • 読み込みが超速い(低レイテンシ)
  • 大量のランダムアクセスにも強い(ランダムI/O)
  • 連続的な読み取りにも強い(シーケンシャル読み取り)

概要

使用場面としては、主に、DB(MySQL)の処理中、以下のような一時的なデータが作られるときに使われます。

  • ソートが必要なクエリ
  • グループ化や集約(集計)の処理
  • 大量のデータを結合するクエリ(JOIN)
  • WITH句(共通テーブル式)を使うクエリ
  • インデックスがない列への検索

これらは一時ファイルや一時テーブルを作るのですが、それをEBSではなくインスタンスストア(高速SSD)で処理することで、パフォーマンスが良くなります。

また、使用するメリットは、下記の通りです。

  • クエリが速くなる(特に複雑な処理や大量のデータに強い)
  • EBSへの負担が減るので、他の処理もスムーズになる
  • デフォルトでON(インスタンスタイプが対応していれば設定不要)

ユースケース

具体的なユースケースは以下の通りです。

1. 分析クエリが複雑なとき

WITH句(共通テーブル式、CTE)を多用する、サブクエリ(派生テーブル)を使う、GROUP BY(集計)を使うクエリなど、こういったクエリでは、大量の一時データを裏側で処理します。
その一時データを高速なSSD(インスタンスストア)に置くことで、処理がサクサク進みます。

2. 最適化されていないクエリを大量に処理するリードレプリカ

リードレプリカは読み取り専用のコピーですが、複雑で最適化されていないクエリ(インデックス不足など)をたくさん投げると重くなります。
RDS Optimized Reads を使えば、そうした重いクエリの負荷を軽減できます。

3. 動的レポート機能などで重いクエリが走るとき

ユーザーが画面から選択してレポートを作成するような機能や、GROUP BY や ORDER BY が入った複雑なクエリなどは、毎回違う条件で処理されるため、一時ファイルの使用量が多くなりがちです。
Optimized Reads により、レポート生成が高速化されます。

4. テンポラリテーブル(一時テーブル)を多く使うワークロード

MySQL はクエリの途中で、一時的にデータを保存するテーブルを使うことがあります。
特にディスク上に作られる「オンディスクテンポラリテーブル」は処理が遅くなる原因になります。
これをインスタンスストア上で処理すれば、速くて効率的。

5. 一時テーブルをたくさん作っているかどうかの確認方法

created_tmp_disk_tables という MySQL のステータス変数をチェックすると、ディスク上に一時テーブルが何個作られたかがわかります。
これが多ければ Optimized Reads の導入効果が期待できます。

6. プロシージャやクエリで大規模な一時テーブルを作成する場合

中間結果を保持するために CREATE TEMPORARY TABLE を使ったり、ストアドプロシージャ(データベース内で定義され、保存され、名前で呼び出すことができる一連のSQL命令の集合)の中でテンポラリテーブルを多用するとき、RDS Optimized Reads により、こうした一時データの扱いが格段に速くなります。

7. インデックスがない列に対してソートや集計をしている場合

例えば、インデックスが張られていない列に対して ORDER BY や GROUP BY を使うと、MySQLは一時テーブルを作ります。
ここでも Optimized Reads による高速化が期待できます。

ベストプラクティス

RDS Optimized Reads を効果的に使うには、ストレージや設定の扱い方に少し注意が必要です。以下のポイントを押さえておくと、安定して高速に動作させられます。

1. クエリが失敗したときの備え:リトライ処理を入れる

Optimized Reads はインスタンスストア(一時的な高速ストレージ)を使いますが、その容量が足りなくなると、一時的にクエリが失敗する可能性があります。
対策としては、読み取り専用クエリには再試行(リトライ)処理を入れておくと安心です。

2. ストレージ容量のモニタリング:FreeLocalStorage を監視する

CloudWatch メトリクスの FreeLocalStorage を使えば、インスタンスストアにどれだけ空きがあるかを常時チェックできます。
対策としては、空きが足りないようなら、より大きなインスタンスサイズにスケールアップを検討しましょう。

3. バイナリログのメモリ使用設定を最適化する

バイナリログとは、MySQL が「どんな更新があったか」を記録しておく仕組みです。このログは通常ディスクに書き込まれますが、設定次第でメモリ上に保持できます。
対策としては、binlog_cache_size を増やすと、メモリに保存できる量が増えるので、ディスクへの書き込みが減って速くなります。
ただし、セッションごとに使うメモリが増えるので、アプリの負荷やインスタンスのメモリ量を見ながら調整しましょう。

4. binlog_format の設定に注意する

MySQL のバージョンによって、バイナリログの保存形式(binlog_format)の推奨値が変わります。

MySQLのバージョン 推奨される設定
8.0以前 MIXED
8.4以降 ROW(デフォルト)

ROW はデータ量が増えやすく、バイナリログが大きくなりがちになります。古いバージョンでは MIXED にして、無駄なディスク使用を抑えるのが良いです。

5. internal_tmp_mem_storage_engine と temptable_max_mmap の設定

Optimized Reads を活かすには、内部テンポラリテーブルのストレージ先を明示的に設定するとよいです。
対策としては、internal_tmp_mem_storage_engine を TempTable に設定する、temptable_max_mmap を、インスタンスストアの容量と合わせたサイズにするなどを行うことで、一時テーブルがきちんとインスタンスストアを使うようになります。

6. 1トランザクションに大量の変更はNG!

1つのトランザクションで大量に更新や削除を行うと、大きな一時ファイル(バイナリログキャッシュ)ができて、インスタンスストアがパンクするかもしれません。
対策としては、更新処理は細かく分ける(小さなトランザクションに分割)ことで、安全性&安定性が高まります。

7. binlog_error_action はデフォルトの ABORT_SERVER を使う

これはエラーハンドリングの設定です。binlog_error_action = ABORT_SERVER にしておけば、
バイナリログが破損したときに自動でインスタンスを安全に停止できます。
特にバックアップを使っている DB では、この設定のままにしておくのがベストです。

RDS Optimized Reads を使う方法とポイント

利用できる条件としては、RDS for MySQL で次のような構成にすると、自動的に RDS Optimized Reads が有効になります。

  • シングル AZ DB インスタンス
  • マルチ AZ DB インスタンス
  • Multi-AZ DB クラスター

さらに、次のいずれかの DB インスタンスクラス を使う必要があります。

db.m5d, db.m6gd, db.r5d, db.r6gd, db.x2iedn, db.z1d など(NVMe SSD を搭載したインスタンス)

また、RDS Optimized Reads を有効にするには、以下のどちらかを行います。

  • 上記の DB インスタンスクラスを使って新しい RDS for MySQL インスタンスまたは Multi-AZ クラスターを作成する
  • 既存の RDS for MySQL インスタンスまたはクラスターを、対応する DB インスタンスクラスに変更する

そして、対応リージョンと確認方法は、RDS Optimized Reads は、NVMe SSD を搭載したインスタンスクラスが利用可能なすべてのリージョンで使えます。
RDS Optimized Reads を使いたくない場合は、これをサポートしていない DB インスタンスクラスに変更すれば無効になります。

参考

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/rds-optimized-reads.html

Discussion