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 ライフを!