Hatena::ブログ(Diary)

ablog このページをアンテナに追加 RSSフィード

2017-12-11

RDS PostgreSQL で大量にセッションを張った場合のメモリ使用量を調べる

RDS PostgreSQL に pgbench で 2000 セッション張って負荷をかけてみたところ、12.5GBほどあった空きメモリを使い尽くして、2GB以上スワップした。

プロセス自体のメモリ、ワーク領域、ページテーブル(PTE)などで1セッションあたり、6MB以上は使っている計算になる。


検証

pgbench を以下で2つ同時に実行して、負荷をかけた。

% pgbench -r -c 1000 -j 1000 -t 100000 -U awsuser -h pg-m4xlarge-master-6.******.ap-northeast-1.rds.amazonaws.com -d mydb

結果

AWSマネジメントコンソールの CloudWatch メトリックスで確認してみた。

f:id:yohei-a:20171211190130p:image:w640

f:id:yohei-a:20171211190125p:image:w640

f:id:yohei-a:20171211190121p:image:w640


環境

  • db.m4.xlarge*1
    • vCPU: 4
    • メモリ: 16GB

参考

ローカルメモリ量 = プロセスのスタック領域
                  + 一時テーブルを使用するデータベースセッションで消費されるメモリ
                  + ソートやハッシュテーブル操作を行うデータベースセッションで消費されるメモリ
                  + 保守操作で消費されるメモリ
                  + プロセス毎に消費される基礎メモリ
                  + データアクセスの準備のために消費されるメモリ
プロセス毎に消費される基礎メモリ
  =  3メガバイト × (max_connections + autovacuum_max_workers + 9)
H.1 FUJITSU Enterprise Postgresで使用するメモリの見積り式

2017-12-09

Redshift 検証メモ

まとめ

  • 「SVV_TABLE_INFO.TBL_ROWS」 で削除対象としてマークされた行も含めた行数を確認できる
  • 「SVV_TABLE_INFO.TBL_ROWS」 - 「select count(*) from テーブル名」が削除済としてマークされた行数
    • STV_TBL_PERM、SVV_DISKUSAGE も同様に削除済としてマークされた行数を含んだ行数を返す
  • VACCUME すると削除された行が解放され、「SVV_TABLE_INFO.TBL_ROWS」と「select count(*) from テーブル名」が一致する

データロード後

  • テーブルを作成する
CREATE TABLE customer (
  c_custkey     	integer        not null,
  c_name        	varchar(25)    not null,
  c_address     	varchar(25)    not null,
  c_city        	varchar(10)    not null,
  c_nation      	varchar(15)    not null,
  c_region      	varchar(12)    not null,
  c_phone       	varchar(15)    not null,
  c_mktsegment      varchar(10)    not null)
diststyle all;
  • ロードする
mydb=# copy customer from 's3://awssampledbuswest2/ssbgz/customer' 
credentials 'aws_access_key_id=<Your-Access-Key-ID>;aws_secret_access_key=<Your-Secret-Access-Key>' 
gzip compupdate off region 'us-west-2';

INFO:  Load into table 'customer' completed, 3000000 record(s) loaded successfully.
COPY
  • テーブルの情報を確認する
mydb=# \i table_info.sql
 schema |   table   | tableid |  distkey  |  skew  | sortkey | #sks |   rows    | mbytes | enc |        pct_enc        | pct_of_total | pct_stats_off | pct_unsorted
--------+-----------+---------+-----------+--------+---------+------+-----------+--------+-----+-----------------------+--------------+---------------+--------------
 public | customer  |  139204 | EVEN      | 1.0000 |         |    0 |   3000000 |    188 | Y   | 52.941176470588235200 |         0.04 |          0.00 |
 (1 rows)
  • テーブルの行数を確認する
mydb=# select count(*) from customer;
  count
---------
 3000000
(1 row)

mydb=# select * from SVV_TABLE_INFO where "table" = 'customer';
 database | schema | table_id |  table   | encoded | diststyle | sortkey1 | max_varchar | sortkey1_enc | sortkey_num | size | pct_used | empty | unsorted | stats_off | tbl_rows | skew_sortkey1 | skew_rows
----------+--------+----------+----------+---------+-----------+----------+-------------+--------------+-------------+------+----------+-------+----------+-----------+----------+---------------+-----------
 mydb     | public |   139204 | customer | Y       | EVEN      |          |          25 |              |           0 |  188 |   0.0492 |     0 |          |      0.00 |  3000000 |               |
(1 row)
  • スライス毎の行数を確認する
mydb=# select * from stv_tbl_perm where name = 'customer' order by slice;
 slice |   id   |                                   name                                   |  rows   | sorted_rows | temp | db_id  | insert_pristine | delete_pristine | backup
-------+--------+--------------------------------------------------------------------------+---------+-------------+------+--------+-----------------+-----------------+--------
     0 | 139204 | customer                                                                 | 1500000 |           0 |    0 | 100153 |               0 |               1 |      1
     1 | 139204 | customer                                                                 | 1500000 |           0 |    0 | 100153 |               0 |               1 |      1
  6411 | 139204 | customer                                                                 |       0 |           0 |    0 | 100153 |               3 |               0 |      1
(3 rows)
  • スライス毎のブロック数を確認する
mydb=# select name, slice, count(*) as mb  from svv_diskusage
where name = 'customer'
group by name, slice;
                                   name                                   | slice | mb
--------------------------------------------------------------------------+-------+----
 customer                                                                 |     1 | 94
 customer                                                                 |     0 | 94
(2 rows)

DELETE後

  • 削除する
mydb=# delete from customer;
DELETE 3000000
mydb=# commit;
COMMIT
  • テーブルの件数を確認する
mydb=# select count(*) from customer;
 count
-------
     0
(1 row)

mydb=# select * from SVV_TABLE_INFO where "table" = 'customer';
 database | schema | table_id |  table   | encoded | diststyle | sortkey1 | max_varchar | sortkey1_enc | sortkey_num | size | pct_used | empty | unsorted | stats_off | tbl_rows | skew_sortkey1 | skew_rows
----------+--------+----------+----------+---------+-----------+----------+-------------+--------------+-------------+------+----------+-------+----------+-----------+----------+---------------+-----------
 mydb     | public |   139204 | customer | Y       | EVEN      |          |          25 |              |           0 |  188 |   0.0492 |     0 |          |      0.00 |  3000000 |               |
(1 row)
  • スライス毎の行数を確認する
mydb=# select * from stv_tbl_perm where name = 'customer' order by slice;
 slice |   id   |                                   name                                   |  rows   | sorted_rows | temp | db_id  | insert_pristine | delete_pristine | backup
-------+--------+--------------------------------------------------------------------------+---------+-------------+------+--------+-----------------+-----------------+--------
     0 | 139204 | customer                                                                 | 1500000 |           0 |    0 | 100153 |               0 |               1 |      1
     1 | 139204 | customer                                                                 | 1500000 |           0 |    0 | 100153 |               0 |               1 |      1
  6411 | 139204 | customer                                                                 |       0 |           0 |    0 | 100153 |               3 |               0 |      1
(3 rows)
  • スライス毎のブロック数を確認する
mydb=# select name, slice, count(*) as mb  from svv_diskusage
where name = 'customer'
group by name, slice;
                                   name                                   | slice | mb
--------------------------------------------------------------------------+-------+----
 customer                                                                 |     1 | 94
 customer                                                                 |     0 | 94
(2 rows)

ANALYZE後

  • ANALYZE する
mydb=# set analyze_threshold_percent to 0;
SET
mydb=# analyze customer all columns;
ANALYZE
  • テーブルの件数を確認する
mydb=# select count(*) from customer;
 count
-------
     0
(1 row)

mydb=# select * from SVV_TABLE_INFO where "table" = 'customer';
 database | schema | table_id |  table   | encoded | diststyle | sortkey1 | max_varchar | sortkey1_enc | sortkey_num | size | pct_used | empty | unsorted | stats_off | tbl_rows | skew_sortkey1 | skew_rows
----------+--------+----------+----------+---------+-----------+----------+-------------+--------------+-------------+------+----------+-------+----------+-----------+----------+---------------+-----------
 mydb     | public |   139204 | customer | Y       | EVEN      |          |          25 |              |           0 |  188 |   0.0492 |     0 |          |      0.00 |  3000000 |               |
(1 row)
  • スライス毎の行数を確認する
mydb=# select name, slice, sum(rows) from stv_tbl_perm
where name = 'customer'
group by name, slice;
                                   name                                   | slice |   sum
--------------------------------------------------------------------------+-------+---------
 customer                                                                 |  6411 |       0
 customer                                                                 |     0 | 1500000
 customer                                                                 |     1 | 1500000
(3 rows)
  • スライス毎のブロック数を確認する
mydb=# select name, slice, count(*) as mb  from svv_diskusage
where name = 'customer'
group by name, slice;
                                   name                                   | slice | mb
--------------------------------------------------------------------------+-------+----
 customer                                                                 |     1 | 94
 customer                                                                 |     0 | 94
(2 rows)

VACUUM後

  • VACUUM する
mydb=# vacuum full customer;
VACUUM
  • テーブルの件数を確認する
mydb=# select count(*) from customer;
 count
-------
     0
(1 row)

mydb=# select * from SVV_TABLE_INFO where "table" = 'customer';
 database | schema | table_id |  table   | encoded | diststyle | sortkey1 | max_varchar | sortkey1_enc | sortkey_num | size | pct_used | empty | unsorted | stats_off | tbl_rows | skew_sortkey1 | skew_rows
----------+--------+----------+----------+---------+-----------+----------+-------------+--------------+-------------+------+----------+-------+----------+-----------+----------+---------------+-----------
 mydb     | public |   139204 | customer | Y       | EVEN      |          |          25 |              |           0 |   22 |   0.0057 |     0 |          |           |        0 |               |
(1 row)
  • スライス毎の行数を確認する
mydb=# select * from stv_tbl_perm where name = 'customer' order by slice;
 slice |   id   |                                   name                                   | rows | sorted_rows | temp | db_id  | insert_pristine | delete_pristine | backup
-------+--------+--------------------------------------------------------------------------+------+-------------+------+--------+-----------------+-----------------+--------
     0 | 139204 | customer                                                                 |    0 |           0 |    0 | 100153 |               0 |               1 |      1
     1 | 139204 | customer                                                                 |    0 |           0 |    0 | 100153 |               0 |               1 |      1
  6411 | 139204 | customer                                                                 |    0 |           0 |    0 | 100153 |               3 |               0 |      1
(3 rows)
  • スライス毎のブロック数を確認する
mydb=# select name, slice, count(*) as mb  from svv_diskusage
where name = 'customer'
group by name, slice;
                                   name                                   | slice | mb
--------------------------------------------------------------------------+-------+----
 customer                                                                 |     1 | 11
 customer                                                                 |     0 | 11
(2 rows)

参考

SVV_TABLE_INFO

データベースのテーブルに関する概要情報を表示します。ビューではシステムテーブルが絞り込まれ、ユーザー定義テーブルのみが表示されます。

SVV_TABLE_INFO ビューを使用して、クエリのパフォーマンスに影響する可能性のあるテーブル設計の問題を診断し、対応できます。これには、圧縮エンコード分散キー、ソートスタイル、データ分散スキュー、テーブルサイズ、および統計情報が含まれます。SVV_TABLE_INFO ビューは、空のテーブルの情報を返しません。

SVV_TABLE_INFO ビューには、STV_BLOCKLIST、STV_PARTITIONS、STV_TBL_PERM、および STV_SLICES システムテーブルと、PG_DATABASE、PG_ATTRIBUTE、PG_CLASS、PG_NAMESPACE、および PG_TYPE カタログテーブルからの概要情報が表示されます。

テーブルの列

列名データ型説明
tbl_rowsnumeric(38,0)テーブル内の合計行数。この値には、削除対象としてマークされ、まだバキューム処理されていない列が含まれます。
SVV_TABLE_INFO - Amazon Redshift

STV_TBL_PERM

STV_TBL_PERM テーブルには、現在のセッション用にユーザーが作成した一時テーブルを含め、Amazon Redshift の永続テーブルに関する情報が表示されます。STV_TBL_PERM には、すべてのデータベース内のすべてのテーブルに関する情報が含まれます。

このテーブルは、クエリの処理中にシステムが作成する一時的なデータベーステーブルの情報を表示する STV_TBL_TRANS とは異なります。

テーブルの列

列名データ型説明
sliceintegerテーブルに割り当てられたノードスライス。
namecharacter(72)テーブル名。
rowsbigintスライス内のデータ行数。
sorted_rowsbigintディスク上でソート済みの、スライス内の行数。この数が ROWS の数と異なる場合は、テーブルに vacuum を実行して行をソートし直してください。
STV_TBL_PERM - Amazon Redshift

SVV_DISKUSAGE

Amazon Redshift は STV_TBL_PERM テーブルと STV_BLOCKLIST テーブルを結合して、SVV_DISKUSAGE システムビューを作成します。SVV_DISKUSAGE ビューにはデータベースのテーブルに対するデータ割り当てに関する情報が含まれます。

次の例で示されているように集計クエリを SVV_DISKUSAGE と一緒に使用すると、データベースあたり、テーブルあたり、スライスあたり、列あたりに割り当てられたディスクブロックの数が算出されます。各データブロックのサイズは 1 MB です。または STV_PARTITIONS を使用して、ディスク利用に関する概要を見ることができます。

テーブルの列

列名データ型説明
db_idintegerデータベース ID。
namecharacter(72)テーブル名。
sliceintegerテーブルに割り当てられたデータスライス。

SVV_DISKUSAGE には割り当て済みディスクブロックにつき 1 つの行が含まれるため、すべての行を選択するクエリを実行すると非常に多数の行が返される可能性があります。SVV_DISKUSAGE を使用した集計クエリのみを使用することをお勧めします。

SVV_DISKUSAGE - Amazon Redshift

関連

2017-09-15

MySQL で NOT NULL 制約のある列に複数行インサートするとその型のデフォルト値が入る

MySQLSQL モードが STRICT モードでない場合、NOT NULL 制約のある列に複数行インサートするとその型のデフォルト値(0とか空文字)が入る(1行インサートだとエラーで入らない)。


検証結果

  • Amazon Aurora with MySQL Compatibility に接続する
$ mysql -h ******.******.ap-northeast-1.rds.amazonaws.com -u awsuser -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 53
Server version: 5.6.10 MySQL Community Server (GPL)

Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> use mydb;
Database changed
  • テーブルを作成する
mysql> create table `not_null_test` (
    ->   `id` int(10) unsigned not null,
    ->   `int_col` int(10) unsigned not null,
    ->   `char_col` char(10)  not null,
    ->   `ts_col` timestamp not null,
    ->   primary key (`id`)
    -> ) engine=innodb default charset=utf8;
Query OK, 0 rows affected (0.05 sec)
  • SQL モードは設定されていない
mysql> select @@global.sql_mode;
+-------------------+
| @@global.sql_mode |
+-------------------+
|                   |
+-------------------+
1 row in set (0.02 sec)
  • 1行インサートはエラーになる
mysql> insert into not_null_test (id, int_col, char_col, ts_col) values (1, null, null, null);
ERROR 1048 (23000): Column 'int_col' cannot be null
  • 複数行インサートは成功する
mysql> insert into not_null_test (id, int_col, char_col, ts_col) values (1, null, null, null), (2, null, null, null);
Query OK, 2 rows affected, 4 warnings (0.02 sec)
Records: 2  Duplicates: 0  Warnings: 4
  • テーブルのデータを確認する
mysql> select * from not_null_test;
+----+---------+----------+---------------------+
| id | int_col | char_col | ts_col              |
+----+---------+----------+---------------------+
|  1 |       0 |          | 2017-09-15 06:54:07 |
|  2 |       0 |          | 2017-09-15 06:54:07 |
+----+---------+----------+---------------------+
2 rows in set (0.02 sec)
  • SQLモードを STRICT_ALL_TABLES にする
mysql> set sql_mode='strict_all_tables';
Query OK, 0 rows affected (0.03 sec)
  • 1行インサートは失敗する
mysql> insert into not_null_test (id, int_col, char_col, ts_col) values (1, null, null, null);
ERROR 1048 (23000): Column 'int_col' cannot be null
  • 複数行インサートも失敗する
mysql> insert into not_null_test (id, int_col, char_col, ts_col) values (1, null, null, null), (2, null, null, null);
ERROR 1048 (23000): Column 'int_col' cannot be nul

参考

単列インサートの場合はNOT NULLが指定されたカラムにNULL値が挿入されるとそのクエリはエラーとなって失敗するが、複数列インサートの場合は警告(warning)を発するものの、クエリは正常に受け付けられる。

その際、NULL値が指定された各カラムにはそれぞれのカラムのデータ型の暗黙的なデフォルト値が挿入される。(数値型なら0、文字列型なら空文字''、etc…)

MySQLにおけるNOT NULLカラムへのインサート時の挙動 - Sojiro’s Blog

NOT NULL として宣言されているカラムへの NULL の挿入。複数行の INSERT ステートメントまたは INSERT INTO ... SELECT ステートメントの場合、このカラムは、そのカラムデータ型の暗黙のデフォルト値に設定されます。これは、数値型では 0、文字列型では空の文字列 ('')、および日付と時間型では「0」の値です。サーバーは SELECT からの結果セットを検査して、それが単一行を返すかどうかを確認しないため、INSERT INTO ... SELECT ステートメントは複数行の挿入と同じ方法で処理されます。(単一行の INSERT の場合は、NULL が NOT NULL カラムに挿入されても警告は発生しません。代わりに、このステートメントがエラーで失敗します。)

MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.2.5 INSERT 構文

明示的な DEFAULT 句のない NOT NULL カラムに対するデータエントリでは、INSERT または REPLACE ステートメントにカラムの値を含まれていない場合、または UPDATE ステートメントがカラムを NULL に設定する場合、MySQL はその時点で有効な SQL モードに従ってカラムを処理します。

  • 厳密な SQL モードを有効にした場合、トランザクションテーブルに対してエラーが発生し、ステートメントがロールバックされます。非トランザクションテーブルではエラーが起きるが、これが複数行ステートメントの 2 行目以降の行に対するエラーの場合、先行する行が挿入されています。
  • 厳密モードが有効でない場合、MySQL はカラムデータ型の暗黙的なデフォルト値にカラムを設定します。

(中略)

セクション5.1.7「サーバー SQL モード」を参照してください。

所定のテーブルに対して、SHOW CREATE TABLE ステートメントを使用すると、どのカラムに明示的な DEFAULT 句があるかを確認できます。

暗黙的なデフォルトは次のように定義されます。

  • 数値型のデフォルトは 0 です。ただし、例外として AUTO_INCREMENT 属性で宣言された整数型または浮動小数点型のデフォルトは、そのシーケンスの次の値になります。
  • TIMESTAMP 以外の日付と時間型のデフォルトには、「ゼロ」値が適切です。explicit_defaults_for_timestamp システム変数が有効な場合、これは TIMESTAMP にも当てはまります (セクション5.1.4「サーバーシステム変数」を参照してください)。それ以外の場合、テーブルの最初の TIMESTAMP カラムのデフォルト値は現在の日付と時間になります。セクション11.3「日付と時間型」を参照してください。
  • ENUM ではない文字列型のデフォルト値は空の文字列です。ENUM のデフォルトは、最初の列挙値です。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 11.6 データ型デフォルト値

厳密モードは、MySQL が INSERT や UPDATE などのデータ変更ステートメントで無効な値または欠落した値を処理する方法を制御します。値はいくつかの理由で無効になることがあります。たとえば、カラムに対して正しくないデータ型を持っていたり、範囲外であったりすることがあります。値の欠落が発生するのは、挿入される新しい行の非 NULL カラムに値が含まれておらず、そのカラムに明示的な DEFAULT 句が定義されていない場合です。(NULL カラムの場合、値が欠落しているときは NULL が挿入されます。)

厳密モードが有効でない場合、MySQL は無効または欠落した値に対して調整された値を挿入し、警告を生成します (セクション13.7.5.41「SHOW WARNINGS 構文」を参照してください)。厳密モードでは、INSERT IGNORE または UPDATE IGNORE を使用すると、この動作を実行できます。

データを変更しない SELECT などのステートメントの場合、厳密モードでは無効な値はエラーでなく警告を生成します。

厳密モードは、外部キー制約が検査されるかどうかに影響されません。foreign_key_checks を検査に使用できます。(セクション5.1.4「サーバーシステム変数」を参照してください。)

MySQL :: MySQL 5.6 リファレンスマニュアル :: 5.1.7 サーバー SQL モード

2017-09-10

Big Data Architecture Pattern (Polyglot/Lambda/Kappa)

仕事の都合で残念ながら聞けなかったが、db tech showcase 2017 での諸橋さんのセッション「polyglot data acces」の内容を polyglot data access - JPOUG in 15 minutes at db tech showcase Tokyo 2017 - wmo6hash::blog で拝見した。とても勉強になる内容だったのでメモ。

f:id:yohei-a:20170911012430p:image

An Enterprise Architect’s Guide to Big Data Reference Architecture Overview より


Big Data Architecture Patterns

Polyglot
  • 透過的にデータベースから外部のデータソースにアクセスする構成
Lambda
  • Twitter(当時) の Nathan 氏が挙げたアーキテクチャ*1
  • バッチレイヤとリアルタイムレイヤを並行して実行し、結果をマージして表示する構成
Kappa
  • LinkedIn(当時) の Jay 氏が挙げたアーキテクチャ*2
  • Lambda Architectureの複雑性に対して問題を提起
  • ストリーム処理システムでバッチと同様の 精度を保証する対処をして構成をシンプル化 した構成

今回の dbts で佐藤さんが紹介していた Apache Kudu*3 や Big Query の Stream Insert は Lambda アーキテクチャのような複雑が不要でシンプルだと思う。

2017-09-04

pgbench で RDS PostgreSQL のマスターに負荷をかけてリードレプリカのレプリケーションラグを計測する

pgbench とは

pgbenchとは

pgbenchはPostgreSQLに同梱されているシンプルなベンチマークツールです。最初のバージョンは筆者により作成され、日本のPostgreSQLメーリングリストで1999年に公開されました。その後pgbenchはcontribという付属追加プログラムとして、PostgreSQLのソースコードとともに配布されるようになりました。どのバージョンでPostgreSQLに取り込まれたのかはPostgreSQL付属のドキュメント(HISTORY)には書かれていないので定かではないのですが、コミットログを見ると、おそらく2000年にリリースされたPostgreSQL 7.0で導入されたと思われます。その後数多くの改良がたくさんの人によって行われ、現在に至っています。

(中略)

pgbenchが標準で実行するトランザクションはTPC-Bを想定しているものとはいえ、実際に使ってみると不都合なこともあります。特に問題なのは、上記ステップ4で、pgbench_branchesの行数がスケーリングファクタと同じ(つまりデフォルトでは10)しかないため、同時接続数が10を超えるとロック競合が発生して性能が出なくなるということです。現実のシステムではこのような設計は普通は行わないので、実際のシステムでの性能を推し量るという、ベンチマーク本来の目的にはあまりそぐわないことになります。

そこでpgbenchでは3と4の処理を省略したトランザクションのモードを用意しており、pgbenchを実行するときに"-N"を付けることによって実行できます。Webシステムのように、多数の同時接続を想定している場合は、こちらを使うことをお勧めします。

pgbenchの使いこなし | Let's Postgres

準備

RDS PostgreSQL のマスターとリードレプリカを作成する
EC2 から RDS PostgreSQL に接続してセットアップする
  • EC2 に psql と pgbench をインストールする。
$ sudo yum -y install postgresql
$ sudo yum -y install postgresql-contrib
$ pgbench -i -s 1000 -U awsuser -h ******.******.ap-northeast-1.rds.amazonaws.com -d mydb
  • テーブルを確認する
$ psql "host=******.*******.ap-northeast-1.rds.amazonaws.com user=awsuser dbname=mydb port=5432"
Password:
mydb=> select * from pg_tables where schemaname='public';
 schemaname |    tablename     | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity
------------+------------------+------------+------------+------------+----------+-------------+-------------
 public     | pgbench_branches | awsuser    |            | t          | f        | f           | f
 public     | pgbench_tellers  | awsuser    |            | t          | f        | f           | f
 public     | pgbench_accounts | awsuser    |            | t          | f        | f           | f
 public     | pgbench_history  | awsuser    |            | f          | f        | f           | f
(4 rows)

mydb=> select count(1) from pgbench_branches;
 count
-------
  1000
(1 row)

mydb=> select count(1) from pgbench_tellers;
 count
-------
 10000
(1 row)

mydb=> select count(1) from pgbench_history;
 count
-------
     0
(1 row)

mydb=> select count(1) from pgbench_accounts;
   count
-----------
 100000000
(1 row)

ベンチマーク実施

  • マスターにトランザクションを発行して負荷をかける
    • N: pgbench_tellersとpgbench_branchesを更新しない。マスターでロック競合がボトルネックになるとトランザクションのスループットが伸びずレプリケーション意外のボトルネックで頭打ちになる可能性があるため。
    • r: ステートメント毎の平均レイテンシをレポートする
    • c: クライアント数
    • j: ワーカースレッド数
    • t: トランザクション数
    • U: DBユーザー名
    • d: データベース
$ pgbench -r -c 10 -j 10 -t 10000 -U awsuser -h ******.******.ap-northeast-1.rds.amazonaws.com -d mydb 

(中略)

transaction type: TPC-B (sort of)
scaling factor: 1000
query mode: simple
number of clients: 10
number of threads: 10
number of transactions per client: 10000
number of transactions actually processed: 100000/100000
tps = ***.****** (including connections establishing)
tps = ***.****** (excluding connections establishing)
statement latencies in milliseconds:

(中略)

	*.********	BEGIN;
	*.********	UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
	*.********	SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
	*.********	UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
	*.********	UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
	*.********	INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
	*.********	END;
  • リードレプリカでレプリケーションラグを確認する
    • マネジメントコンソールの「レプリケーションの詳細」でも確認できる
    • 以下の単位は秒
$ psql "host=******.******.ap-southeast-1.rds.amazonaws.com user=awsuser dbname=mydb port=5432"
Password:

mydb=> SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::INT;

 date_part
-----------
       0
(1 row)

mydb=> SELECT EXTRACT(EPOCH FROM (now() - pg_last_xact_replay_timestamp()))::INT;
 date_part
-----------
       0
(1 row)
  • マネジメントコンソールの「モニタリング」の「トランザクションログの生成」でトランザクションログの生成量を確認する。

参考