Amazon RDS for PostgreSQLが読み込み性能を最大で2倍にする最適化読み込みに対応しました

書き込み最適化はまだ
2023.04.11

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

Amazon RDS for PostgreSQLが読み込み性能を追加費用無しに最大で2倍にする最適化読み込み(optimized reads)に対応しました。

Amazon RDS Optimized Reads now offers up to 2X faster queries on RDS for PostgreSQL

昨年末にAmazon RDS for MySQLが読み書きの最適化に対応しましたが、今回のPostgreSQLは「読み込み」に特化した対応となっています。

インスタンスタイプとバージョンの要件を満たしていれば、デフォルト、かつ、無料でご利用いただけます。

最適化読み込みのユースケース

RDS for PostgreSQLの最適化読み込みのユースケースは、MySQLと同じです。

  • 共通テーブル式(CTE)、派生テーブル、グループ化操作を含む分析クエリ
  • アプリケーションの最適化されていないクエリを処理するリードレプリカ
  • GROUP BYやORDER BYなどの複雑な操作で、常に適切なインデックスを使用できないオンデマンドまたはダイナミックレポートクエリ
  • その他、内部テンポラリテーブルを使用するワークロード

最適化読み込みの効果

AWS公式のデータベースブログにおいて、一時ストレージが必要なワークロードを実行する際、並列度が増えるにつれて最適化読み込みが有効であることを示すベンチマークが紹介されています。

※ 図は公式ブログから

要件

以下の条件を満たすようにRDSインスタンスを作成・変更すると、最適化読み込みがデフォルトで有効になります。

  • バージョン : 15.2以上、または、14.7以上、または、13.10以上
  • インスタンスクラス : db.m6gd/db.r6gd/db.m5d/db.r5d
  • リージョン : Beijing/Ningxia 以外

最適化読み込みの秘訣はローカルストレージ

要件のインスタンスクラス(すべてdが接尾)からわかるように、最適化読み込みに対応したRDSインスタンスは、NVMeの揮発性ローカルストレージがあります。 PostgreSQLのテーブルスペース機能を利用し、セッション関連のデータなどを rds_temp_tablespace というスペース名でこのNVMe(/rdslocalstorage/rds_temp_tablespace)に向けています。

この対応により、EBSよりもNVMeのIOPSのほうが高いのはもちろんのこと、Amazon EBSへの通信時のネットワークI/Oレイテンシーが改善します。 また、ストレージレイヤーレベルでEBSの全データがレプリケートされるマルチAZインスタンス環境では、NVMeにある一時データがレプリケートされなくなるため、パフォーマンスが向上します。

postgres=> show temp_tablespaces;
  temp_tablespaces
---------------------
 rds_temp_tablespace
(1 row)

postgres=> SELECT spcname,pg_tablespace_location(oid) FROM pg_tablespace 
  WHERE pg_tablespace_location(oid) LIKE '%local%';
       spcname       |        pg_tablespace_location
---------------------+--------------------------------------
 rds_temp_tablespace | /rdslocalstorage/rds_temp_tablespace
(1 row)

最適化読み込みが有効でない場合、これらSQLの実行結果はブランクです。

注意

最適化読み込みはローカル依存ストレージに強く依存しています。 例えば、ローカルストレージがいっぱいになると、トランザクションが失敗します。 そのため、以下の対応を行いましょう。

  • クエリ失敗に備え、リトライ処理を追加
  • インスタンスレベルのCloudWatch Metricsでローカルストレージを監視
    • FreeLocalStorage
    • ReadIOPSLocalStorage
    • ReadLatencyLocalStorage
    • ReadThroughputLocalStorage
    • WriteIOPSLocalStorage
    • WriteLatencyLocalStorage
    • WriteThroughputLocalStorage

試しに、マンデルブロー集合を描くSQLを走らせたあとに、ローカルストレージを確認してみましょう。

postgres=> SELECT
    spcname AS "Name",
    pg_catalog.pg_size_pretty(pg_catalog.pg_tablespace_size(oid)) AS "size"
FROM
    pg_catalog.pg_tablespace
WHERE
    spcname IN ('rds_temp_tablespace');
        Name         |    size
---------------------+------------
 rds_temp_tablespace | 4096 bytes
(1 row)

ローカルストレージを 4096バイト消費していますね。

RDS for PostgreSQLの最適化書き込みはいつ?

RDS for MySQLは読み書きともに最適化されているのに対して、PostgreSQLは読み込みだけです。

MySQLの場合は、Torn Write Prevention機能を導入してDouble Buffer Write を止め、最適化書き込みを実現しました。

PostgreSQLの場合、Buffered I/Oの非効率さがしばしば指摘されてきました。最近ではPostgreSQL 16に O_DIRECT(Direct I/O)のための設定が入ったりと、書き込み改善の布石が打たれています。将来が楽しみですね。

参考