なからなLife

geekに憧れと敬意を抱きながら、SE、ITコンサル、商品企画、事業企画、管理会計、総務・情シス、再び受託でDB屋さんと流浪する人のブログです。

AWS RDSの各種DBにおけるメモリ管理の指定方法

超親切設計な、インスタンスサイズからの自動計算、だけど

パラメータグループには、デフォルトでDBInstanceClassMemoryからの自動計算になっていて、インスタンスサイズの変更時に手動でパラメータ変更をする必要がないような超親切設計になっています。

しかし、これを単純に逆算すると、どうしてもインスタンスタイプの搭載メモリとして公開されている値に一致しないんです。わりとみんな通る道。


この件、ドキュメントにもちゃんと書いてあって、

DBInstanceClassMemory
現在の DB インスタンスに関連付けられている DB インスタンスクラスに割り当てられたメモリから、インスタンスを管理する Amazon RDS プロセスによって使用されるメモリを引いたバイト数を返します。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_WorkingWithParamGroups.html#USER_FormulaVariables

この「引かれる数」が明示されてないのですね。

なので、多少ずれるものと思ってください。

各種DBのデフォルト計算と、PostgreSQLの落とし穴?

各種DB毎のパラメータとデフォルト計算式は、以下のようになっています。


PostgreSQL
RDS PostgreSQL shared_buffers {DBInstanceClassMemory/32768}
Aurora PostgreSQL shared_buffers SUM({DBInstanceClassMemory/12038},-50003)

純正PostgreSQLだと、postgresql.confのshared_buffersにバイト指定(KB、MBなど単位指定可)なのに、AWSの世界に来ると、なぜか「ブロック数」指定となる。(1ブロック=8KB)
誰得?

実際に適用された値を「SHOW shared_buffers」で確認すると、RDSの方はインスタンスのメモリ総量の約25%で、PostgreSQLのセオリー通りの値になってます。

一方Auroraは、インスタンスのメモリ総量の約75%を割り当てています。ノーマルなPostgreSQLとはメモリ戦略が違うんですね。

追記
RDSとAuroraでshared_buffersの比率が違う理由は、AWSから公式に説明されていました。
Shared_Buffers DB パラメータのデフォルト値と Amazon RDS PostgreSQL および Aurora PostgreSQL の間に差がある理由を理解する

MySQL

バイト指定です。インスタンスのメモリ総量の約75%を素直に計算しています。
RDS MySQL

innodb_buffer_pool_size {DBInstanceClassMemory*3/4}
innodb_buffer_pool_size {DBInstanceClassMemory*3/4}

シンプルに、セオリー通りの値を当てています。

Oracle

バッファの種類自体がたくさんあるのですが、その細かい内容には言及しません。が、素直にバイト単位指定です。

memory_max_target IF({DBInstanceClassHugePagesDefault}, 0, {DBInstanceClassMemory*3/4})
memory_target IF({DBInstanceClassHugePagesDefault}, 0, {DBInstanceClassMemory*3/4})
sga_target IF({DBInstanceClassHugePagesDefault}, {DBInstanceClassMemory*3/4}, 0)

HugePageが有効だと自動メモリ管理が使えないので、

  • HugePageが無効のときに自動メモリ管理系のパラメータにはインスタンスのメモリ総量の約75%を割り当て
  • HugePageが有効なときには、sga_targetをインスタンスのメモリ総量の約75%を割り当て

となっています。気が利いてる。


HugePageが有効か無効か、という解説はここに書いてあります。
https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/CHAP_Oracle.html

「shared_pool_size」「java_pool_size」「large_pool_size」とかは、パラメータグループ上にデフォルトが設定されていません。
上記URLのページに

sga_max_size = {DBInstanceClassMemory*3/4}
(中略)
sga_max_size = IF({DBInstanceClassHugePagesDefault}, {DBInstanceClassMemory*3/4}, 0)

という記述もあるのですが、パラメータグループにはそのような設定は入ってないので、あくまでHugePageを有効にしたときに自分で入れてね、ということのようです。

SQL Server

これも素直にバイト(メガバイト)指定になっています。

max server memory (mb) {DBInstanceClassMemory/1048576}

SQL Serverについては詳しくないですが、この式自体はByteからMBに換算しているだけです。

Oracleの自動メモリ管理と同じで、ここから純粋なバッファキャッシュ以外のメモリも割り当てるっぽいのですが、それにしても、RDS内部管理プロセス用を引いた残り「全部」なんですね。



まとめ

  • パラメータグループで使用される「DBInstanceClassMemory」は、インスタンスの総メモリサイズ「ではない」、多少引かれた数字。
  • PostgreSQLだけ、RDSとAuroraでメモリ戦略が違う
  • PostgreSQLだけ、postgresql.confとRDSパラメータグループで、shared_buffersの指定単位が違う。

パラメータグループの画面にある「説明」にもそれっぽいことが書いてあるけど、英語だし、画面端っこで見切れたりするんで気づきにくいくんですよね。
アタマの中はpostgresql.confと同じだと思いこんでるし。

慣れてる人なら、もっと手前に表示されている「許可された値」の範囲が「128-」ではなく「16-」(*8KBで128KB=postgresql.confに書くときの最小値になる)と書いてあるので気づくのでしょうけど。


このテーマに合わせて推すべき本に迷いましたが、それぞれのDBについて理解を深めつつ、マネージドなサービスの恩恵に預かりましょう、ということで、各種DB関連書籍で比較的新しいものを。