[PR] あなたが Kindle で読みたいその本、Kindle に対応したら Twitter でお知らせします。

RDS for PostgreSQL で UNLOGGED テーブルを試してみる

Posted on

PostgreSQL 9.1 から CREATE TABLE に UNLOGGED オプションが追加されました。ドキュメントより引用します。

指定された場合、テーブルはログを取らないテーブルとして作成されます。ログを取らないテーブルに書き出されたデータは先行書き込みログには書き出されません。このため通常のテーブルより相当高速になります。(中略)またログを取らないテーブルの内容はスタンバイサーバに複製されません。

WAL ログを出力しないことで信頼性を犠牲にして、書き込み性能を求めることができます。 WAL ログを出力しないためスレーブにも同期されません。信頼性が必要ない一時テーブルにはぴったりのオプションです。

RDS for PostgreSQL で使うとどうなるのか?

ここからが本題です。 RDS for PostgreSQL でも Multi-AZ 配置にすることでスタンバイへ同期されますが、UNLOGGED オプションを付けるとどうなるのか気になりました。 pg_stat_replication テーブルを見ればわかりますが、RDS では PostgreSQL のレプリケーション機能は使われておらず独自の仕組みで同期されています。

というわけで、さっそく検証してみました。

pgbench で検証してみる

PostgreSQL の代表的なベンチマークツール pgbench を使って検証します。外部要因で結果が変わらないように、同じ VPC 内の EC2 から Multi-AZ 配置の RDS に対して pgbench を実行します。 RDS のスペックは以下のとおり。

  • PostgreSQL 9.3.3
  • db.m3.medium
  • 10 GB (No IOPS)

まずは普通のテーブルで基準となる TPS (Transaction Per Second) 値を計測します。 3 クライアントで 1000 トランザクションを実行します。

$ pgbench -U rea -h test.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -i testdb

$ pgbench -v -U rea -h test.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -c 3 -t 1000 testdb
Password: 
starting vacuum...end.
starting vacuum pgbench_accounts...end.
transaction type: TPC-B (sort of)
scaling factor: 1
query mode: simple
number of clients: 3
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 3000/3000
tps = 116.680505 (including connections establishing)
tps = 116.912883 (excluding connections establishing)

TPS は約 117 です。 Provisioned IOPS を指定していないのでこんなもんでしょう。

次に UNLOGGED オプションを付けて検証します。テーブルを初期化するときに --unlogged-tables オプションを付けるだけです。先ほどより良い結果が出れば UNLOGGED オプションの効果があると言えます。

$ pgbench -U rea -h test.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -i --unlogged-tables testdb

$ pgbench -v -U rea -h test.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com -c 3 -t 1000 testdb
Password: 
starting vacuum...end.
starting vacuum pgbench_accounts...end.
transaction type: TPC-B (sort of)
scaling factor: 1
query mode: simple
number of clients: 3
number of threads: 1
number of transactions per client: 1000
number of transactions actually processed: 3000/3000
tps = 557.576771 (including connections establishing)
tps = 564.340455 (excluding connections establishing)

UNLOGGED オプションを付けたことで TPS が約 564 まで伸びました。なんと 4.8 倍の差です!

RDS でなぜ速くなったのか?

この結果だけを見ると UNLOGGED オプションが効くのは間違いなさそうです。

ただ、別の疑問が浮かんできます。最初にも書いたとおり、RDS は独自の仕組みで同期しています。サイトには以下のように書かれています。

MySQL、Oracle、および PostgreSQL エンジンのマルチ AZ 配置は、同期物理レプリケーションを活用して、スタンバイしているデータをプライマリに合わせて最新の状態に維持します。

同期物理レプリケーションとはディスクレベルの同期のことを指しているようです。要するに UNLOGGED オプションを付けたとしても、マスタのディスクに書き込みが発生した時点でスレーブにも同期されるということです。

AWS の開発者サポートに聞いてみた

開発者サポートに入っているので、上記の検証結果を踏まえて問い合わせしてみました。要点をまとめると次の 2 点になります。

  • マスタのディスクに反映されたデータは PostgreSQL のオプションにかかわらずスレーブに同期される
  • RDS にはスレーブに同期させない手段はない

ミドルウェアではなくその下のレイヤーで同期されているので、UNLOGGED オプションを付けてもスレーブに同期されてしまうようです。 pgbench で TPS が大幅に改善されたのは WAL ログを出力するコストがゼロになったためです。

まとめ

ここまでの情報をまとめます。

  • RDS ではミドルウェアではなく、その下のレイヤーでディスク同期を行っている
  • Multi-AZ 配置でスレーブに同期させない手段はない
  • RDS for PostgreSQL で UNLOGGED オプションを付けてもスレーブに同期される
  • ただし、WAL ログを出力するコストがゼロになるので TPS は改善する

よって、一時テーブルなど信頼性が必要ないテーブルには積極的に UNLOGGED オプションを付けてパフォーマンスを改善しましょう。よい RDS ライフを!