#6 pgbenchでお手軽ベンチマーク

本記事は[PostgreSQL on Kubernetes Advent Calendar 2018](https://qiita.com/advent-calendar/2018/postgresonk8s)の6日目です。
昨日は「[pgadminから接続してみる](https://qiita.com/tzkoba/private/7e622e42e8e6867dbe28)」ということで、PostgreSQL on Kubernetesと同じクラスタ内にpgadminが入ったポッドを構築し、データベースを作るところまでやってみました。

本日はpgbenchを使って、テストデータのセットアップと簡易ベンチマークを試してみたいと思います。

# TL;DR

+ pgbenchを使うには、まず-iオプションで初期化しよう。
+ その後は接続数やテスト時間などお好みで調整してベンチマークしてみよう。
+ 結果はpgadminで見ると分かりやすいよ。


# 構築済みの構成
第5回でpgadminとpgbenchを同梱したポッドを以下のツール用サーバに導入しました。

+ 1台のツール用サーバ。Kubernetes上でラベルとして、type=node.mon.bench が付いていること

# pgbenchを使ってみよう
pgbenchはPostgreSQLに同梱されているベンチマークツールです。
使い方は有名な[Let's Postgres](https://lets.postgresql.jp/documents/technical/contrib/pgbench)でも紹介されているのですが、今回は無理やり（？）全てをkubectl execで実行してみましょう。

最初にPostgreSQL（StatefulSet）とpgtoolsのポッドを確認しておきましょう。

```shell
$ kubectl get pod
NAME                       READY     STATUS    RESTARTS   AGE
pg-rook-sf-0               1/1       Running   0          3h
pgtools-75fb6bdb95-l859w   2/2       Running   0          8h
```

### テスト用データベースの初期化
まず、テスト用のデータベースにデータをセットアップします。
pgtoolsのポッド内にあるpgbenchコンテナを-cで指定して、pgbenchコマンドを投入します。

```shell
$ kubectl exec -it pgtools-75fb6bdb95-l859w -c pgbench -- /usr/pgsql-10/bin/pgbench -h pg-rook-sf.default.svc -U bench -i -s 100
Password:
creating tables...
100000 of 10000000 tuples (1%) done (elapsed 0.08 s, remaining 7.77 s)
200000 of 10000000 tuples (2%) done (elapsed 1.69 s, remaining 82.65 s)
300000 of 10000000 tuples (3%) done (elapsed 1.79 s, remaining 57.87 s)
400000 of 10000000 tuples (4%) done (elapsed 3.13 s, remaining 75.19 s)
500000 of 10000000 tuples (5%) done (elapsed 3.70 s, remaining 70.27 s)
600000 of 10000000 tuples (6%) done (elapsed 5.03 s, remaining 78.86 s)
-- (中略) --
9700000 of 10000000 tuples (97%) done (elapsed 138.92 s, remaining 4.30 s)
9800000 of 10000000 tuples (98%) done (elapsed 142.57 s, remaining 2.91 s)
9900000 of 10000000 tuples (99%) done (elapsed 142.75 s, remaining 1.44 s)
10000000 of 10000000 tuples (100%) done (elapsed 146.55 s, remaining 0.00 s)
vacuum...
set primary keys...
done.
```

初期化の際に必要なオプションは以下の2つだけです。

+ -i ・・・ このオプションを付けると初期化処理が行われます。
+ -s 数値 ・・・ データ量の規模（scaling factor）を指定します。1を指定した場合、10万件のテストデータが作成されます。上記では-s 100としていますので、1000万件のデータとなります。

なお、注意点としてここで初期化するデータベースには、決してベンチマーク以外の用途のもの（開発用途やテスト用途など）を使わないで下さい。
誤ってそれらのDBを指定して、不幸にもベンチマーク用のものと名称が被ったりすると、テーブルがDROPされるなどの悲劇が起こります。

### ディスク容量を確認しておく
さて、上記の初期化処理で1000万件のデータが入ったはずです。
レコード数やディスク利用量などを確認してみましょう。

```shell
$ kubectl exec -it pg-rook-sf-0 -- psql -h localhost -U bench -c "\d"
             List of relations
 Schema |       Name       | Type  | Owner
--------+------------------+-------+-------
 public | pgbench_accounts | table | bench
 public | pgbench_branches | table | bench
 public | pgbench_history  | table | bench
 public | pgbench_tellers  | table | bench
(4 rows)


$ kubectl exec -it pg-rook-sf-0 -- psql -h localhost -U bench -c "select count(*) from pgbench_accounts"
  count
----------
 10000000
(1 row)
```
PostgreSQLのポッドに直接接続し、作成されたテーブルの一覧、そしてpgbench_accountsというテーブルの件数をカウントしてみました。
確かに10,000,000件が挿入されていますね。

では、ディスク利用量はどうなったでしょうか。

```shell
$ kubectl exec -it pg-rook-sf-0 -- df -h
Filesystem      Size  Used Avail Use% Mounted on
overlay          40G   12G   29G  29% /
tmpfs           1.9G     0  1.9G   0% /dev
tmpfs           1.9G     0  1.9G   0% /sys/fs/cgroup
/dev/xvda1       40G   12G   29G  29% /etc/hosts
shm              64M  8.0K   64M   1% /dev/shm
/dev/rbd1       2.0G   81M  2.0G   4% /mnt/postgresql/xlog
/dev/rbd0       3.0G  2.6G  472M  85% /var/lib/postgresql/data
tmpfs           1.9G   12K  1.9G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs           1.9G     0  1.9G   0% /sys/firmware
```

データディレクトリ（PGDATA）である/var/lib/postgresql/dataの利用量が2.6Gを超えています。
今回準備したストレージからすると、ちょっと入れすぎかもしれませんね。
こうした場合は、-sの値を調整して再度初期化するという対応も可能です。

また、今回のデータベースは後の障害テストに備えて、アーカイブログモードにしています。
そのため、/mnt/postgresql/xlog があふれてしまうことがあるかもしれませんので、そちらは適宜クリーンアップして下さい。
（後日、アーカイブログ削除用のジョブなどを紹介予定です。）

### ベンチマークテストの実行
では、準備したデータに対してベンチマークテストを実行しましょう。

```shell

$ kubectl exec -it pgtools-75fb6bdb95-l859w -c pgbench -- /usr/pgsql-10/bin/pgbench -h pg-rook-sf.default.svc -U bench -c 2 -T 180 -l --aggregate-interval=60 bench
Password:
starting vacuum...end.
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 100
query mode: simple
number of clients: 2
number of threads: 1
duration: 180 s
number of transactions actually processed: 34186
latency average = 10.531 ms
tps = 189.914070 (including connections establishing)
tps = 189.920978 (excluding connections establishing)
```

テストが実行され、TPSが表示されました。今回は結果として189TPSと出ています。
ベンチマーク時に良く使うpgbenchの引数は以下となります。

+ -c ・・・同時接続数です。上記では2を指定していますので、2セッションでの実行となります。
+ -T ・・・テストを実行する秒数を指定します。上記では180秒としています。 

その他にもスレッド数やコネクションを毎回張るのか使いまわすのか、など多様なオプションがあります。

### pgadminからも確認できる
実は第5回で導入したpgadminのダッシュボードでも、性能テストの状況をリアルタイムで確認することが出来ます。
以下は性能テスト時のダッシュボード表示ですが、TPSやTuples In/Outが表示されているのが分かるでしょうか。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/54853/b9c5e396-4073-5062-3b91-2e64a432a068.png)

こちらでトランザクション性能の推移を確認することも出来ますね。

# まとめ
今日はCLIベースのツールでしたので、文字多めの投稿となりました。

本日までの構築作業でPostgreSQL on Rookの検証環境がほぼ整いました。
明日からは本番オペレーションを想定した実機検証をしてみたいと思います。

よろしくお願いします。