F.18. pgbench

pgbenchPostgreSQL上でベンチマーク試験を行う単純なプログラムです。 これは同一のSQLコマンドの並びを何度も実行します。複数の同時実行データベースセッションで実行することもできます。 そして、トランザクションの速度(1秒当たりのトランザクション数)の平均を計算します。 デフォルトでpgbenchは、1トランザクション当たり5つのSELECTUPDATEINSERTコマンドを含むおおよそTPC-Bに基いたシナリオを試験します。 しかし、独自のトランザクションスクリプトファイルを作成することで他の試験ケースを簡単に実行することができます。

pgbenchの典型的な出力を以下に示します。

transaction type: TPC-B (sort of)
scaling factor: 10
number of clients: 10
number of transactions per client: 1000
number of transactions actually processed: 10000/10000
tps = 85.184871 (including connections establishing)
tps = 85.296346 (excluding connections establishing)
 

最初の4行はいくつかの最重要パラメータの設定を表示しているだけです。 次行が完了トランザクション数と予定トランザクション数です(後者は単なるクライアント数とトランザクション数の積算結果です。) 実行が完了する前に失敗しない限りこれは等しくなります。 最後の2行は、データベースセッションを開始した時と含める場合と含めない場合のTPS速度を示します。

F.18.1. 概要

TPC-Bのようなトランザクション試験では、デフォルトで事前設定された特定のテーブルを必要とします。 pgbenchでは、こうしたテーブルを作成しデータ投入するために-i(初期化)オプションを付けて呼び出さなければなりません。 (独自スクリプトの試験を行う時はこの処理は不要です。 しかし代わりに、独自試験で必要な何らかの設定を行わなければなりません。) 初期化は以下のように行います。

pgbench -i [ other-options ] dbname
   

ここでdbnameは試験用に前もって作成されたデータベースの名前です。 (またデータベースサーバの接続方法を指定するために、-h-p-Uが必要になるかもしれません。)

注意

pgbench -iは4つのテーブルaccountsbrancheshistorytellersを作成します。 もしあればこうした名前のテーブルは破壊されます。 もし同じ名前のテーブルが存在する場合にはよく注意してください。

デフォルトの"倍数"の1では、テーブルは初期状態で以下の行数が含みます。

table           # of rows
-------------------------
branches        1
tellers         10
accounts        100000
history         0
  

-s(倍数)オプションを使用して行数を増加させることができます(また、ほとんどの目的ではおそらく増加させるべきです)。 また、-F (フィルファクタ)オプションをここで使用しても構いません。

一度この必要な設定を行った後、以下のように-iを持たないコマンドでベンチマークを行うことができます。

pgbench [ options ] dbname
   

ほとんどすべての場合、有用な試験とするためにいくつかのオプションが必要になります。 最重要オプションは-c(クライアント数)、-t(トランザクション数)、-f(独自スクリプトファイルの指定)です。 以下の全一覧を参照してください。

表F-14はデータベース初期化時に使用されるオプションを示します。 表F-15はベンチマーク実行時に使用されるオプションを示します。 そして、表F-16はどちらの場合でも使用されるオプションを示します。

表 F-14. pgbench初期化オプション

オプション説明
-i初期化モードを呼び出すために必要です。
-s scale_factorこの倍率で生成される行数を積算します。 例えば、-s 100accountsテーブルに10,000,000行を生成することを意味します。 デフォルトは1です。
-F fillfactor指定したフィルファクタでaccountstellersbranchesテーブルを作成します。 デフォルトは100です。

表 F-15. pgbenchベンチマーク用オプション

オプション説明
-c clients模擬するクライアント数、つまり、同時に実行されるデータベースセッション数です。 デフォルトは1です。
-t transactions各クライアントが実行するトランザクション数です。 デフォルトは10です。
-Ntellersbranchesを更新しません。 これは両テーブル上の重度の更新の競合を防ぎますが、TPC-Bのような試験ケースを行わなくなります。
-STPC-Bのような試験ではなく読み取りのみのトランザクションを実行します。
-f filenameトランザクションスクリプトをfilenameから読み取ります。 詳細は後で説明します。 -N-S-fは互いに排他的です。
-n試験を実行する前にバキュームを行いません。 accountsbrancheshistorytellers標準テーブルを含まない独自試験シナリオを実行する場合、このオプションは必要です。
-v試験前に4つの標準テーブルすべてをバキュームを行います。 -nまたは-vがなければ、pgbenchはtellersbranchesテーブルをバキュームし、history内のデータをすべて消去します。
-D varname=value独自スクリプト(後述)で使用される変数を定義します。 複数の-Dオプションを使用することができます。
-C各クライアントスレッドが一度だけ接続を確立するのではなく、各トランザクションが新しい接続を確立します。 これは接続オーバーヘッドを測定する場合に有用です。
-l各トランザクションで費やした時間をログファイルに書き出します。 後で詳細を説明します。
-s scale_factorpgbenchの出力で指定した倍率を報告します。 これは組み込みの試験では必要ありません。 正確な倍率がbranchesテーブルの行数を数えることで検出されます。 しかし、独自ベンチマーク(-fオプション)を試験している場合、このオプションを使用しない限り、倍率は1として報告されます。
-dでバック用出力を表示します。

表 F-16. pgbench共通オプション

オプション説明
-h hostnameデータベースサーバのホスト
-p portデータベースサーバのポート
-U login接続ユーザ名

F.18.2. 実際にpgbenchで行われる"トランザクション"は何か?

デフォルトのトランザクションスクリプトは、1トランザクションで以下の7コマンドを発行します。

  1. BEGIN;

  2. UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid;

  3. SELECT abalance FROM accounts WHERE aid = :aid;

  4. UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid;

  5. UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid;

  6. INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);

  7. END;

-Nを指定した場合、第4コマンドと第5コマンドはトランザクションに含まれません。 -Sを指定した場合、SELECTのみが発行されます。

F.18.3. 独自スクリプト

pgbenchは、ファイルから読み込んだトランザクションスクリプト(-fオプション)でデフォルトのトランザクションスクリプト(上述)を置き換えて独自のベンチマークシナリオを実行する機能をサポートします。 この場合、"トランザクション"はスクリプトファイルの1回の実行として数えられます。 複数のスクリプトを指定する(複数の-fオプション)ことさえ可能です。 この場合、クライアントセッションが新しいトランザクションを開始する時にランダムにスクリプトの1つが選択されます。

スクリプトファイルの書式は、1行1 SQLコマンドという形で、複数行に跨るSQLコマンドはサポートされません。 空行および--から始まる行は無視されます。 スクリプトファイルの行には、pgbench自身が解釈する"メタコマンド"(後述)も記述することができます。

スクリプトファイル向けの簡単な変数置換機能があります。 上で説明したように変数を-Dコマンドラインオプションで設定することができます。 また、後で説明するようにメタコマンドで設定することもできます。 -Dコマンドラインオプションで設定された変数の他に、scale変数は現在の倍率に設定されています。 一度設定すると、:variablenameと記述することで変数の値はSQLコマンドに挿入されます。 1つ以上のクライアントセッションを実行する時、セッション毎に独自の変数群を持ちます。

スクリプトファイルメタコマンドはバックスラッシュ(\)から始まります。 メタコマンドへの引数は空白文字で区切られます。 以下のメタコマンドがサポートされています。

\set varname operand1 [ operator operand2 ]

varname変数を計算された整数値に設定します。 各operandは整数定数か整数値を持つ変数への:variablename参照のいずれかです。 operator+-*/を取ることができます。

\set ntellers 10 * :scale
      

\setrandom varname min max

varname変数をminからmaxまでの範囲のランダムな整数値に設定します。 各制限整数定数か整数値を持つ変数への:variablename参照のいずれかです。

\setrandom aid 1 :naccounts
      

\sleep number [ us | ms | s ]

スクリプトの実行をマイクロ秒(us)、ミリ秒(ms)、秒(s)単位で指定した間待機させます。 単位を省略した場合、デフォルトは秒です。 number整数定数か整数値を持つ変数への:variablename参照のいずれかです。

\sleep 10 ms
      

例えば、組込みのTPC-Bのようなトランザクションの完全な定義を示します。

\set nbranches :scale
\set ntellers 10 * :scale
\set naccounts 100000 * :scale
\setrandom aid 1 :naccounts
\setrandom bid 1 :nbranches
\setrandom tid 1 :ntellers
\setrandom delta -5000 5000
BEGIN;
UPDATE accounts SET abalance = abalance + :delta WHERE aid = :aid;
SELECT abalance FROM accounts WHERE aid = :aid;
UPDATE tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
UPDATE branches SET bbalance = bbalance + :delta WHERE bid = :bid;
INSERT INTO history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
END;
   

このスクリプトにより、トランザクションを繰り返す度に異なる、ランダムに選ばれた行を参照することができます。 (この例はまた、各クライアントセッションがなぜ独自の変数を持つことが重要なのかも表しています。 これがないと、異なる行を独立して参照することができないのです。)

F.18.4. トランザクション毎のログ処理

-lオプションを使用すると、pgbenchは各トランザクションで要した時間をログファイルに書き出します。 ログファイルの名前はpgbench_log.nnnです。 ここでnnnはpgbenchプロセスのPIDです。 ログの書式は以下の通りです。

    client_id transaction_no time file_no time_epoch time_us
   

ここでtimeはマイクロ秒単位のトランザクション処理時間、file_noは使用されたスクリプトファイルを識別するもの(-fにより複数のスクリプトが指定された場合に有用)、time_epoch/time_usはマイクロ秒のオフセットを持つUNIXエポック書式のタイムスタンプ(秒部分付きのISO 8601タイムスタンプの作成に適します)でトランザクションの完了時刻を示します。

以下に出力例を示します。

 0 199 2241 0 1175850568 995598
 0 200 2465 0 1175850568 998079
 0 201 2513 0 1175850569 608
 0 202 2038 0 1175850569 2663
   

F.18.5. 優れた実践

まったく無意味な数値を生み出すようにpgbenchを使用することは非常に簡単です。 以下に有意な結果を生み出す手助けとなるガイドラインをいくつか示します。

まず第一に、数秒で終わる試験を決して信用しないでください。 -t設定を増やして、雑音を取り除くために、少なくとも数分試験にかかるようにしてください。 再現可能な数値を得るために数時間必要になる場合もあります。 数回試験を繰り返し、数値が再現できるかどうか確認することを勧めます。

デフォルトのTPC-Bのような試験シナリオでは、初期倍率(-s)を試験予定のクライアント数(-c)の最大値と同程度にしなければなりません。 branchesテーブルには-s行しかありません。 また、前トランザクションはその内の1つを更新しようとします。 ですので、-c値を-sより大きくすると、他のトランザクションを待機するためにブロックされるトランザクションが多くなることは間違いありません。

デフォルトの試験シナリオはまた、テーブルを初期化してからの経過時間に非常に敏感です。 テーブル内の不要行や不要空間の累積により結果が変わります。 結果を理解するためには、更新された行数とバキューム時期を把握する必要があります。 自動バキュームが有効な場合、性能を測定する上で結果は予測できないほど変わる可能性があります。

pgbenchの制限は、多くのクライアントセッションを試験しようとする際にpgbench自信がボトルネックになる可能性があることです。 これは、データベースサーバとは別のマシンでpgbenchを実行することで緩和させることが可能です。 しかし、多少のネットワーク遅延が重要です。 同一データベースサーバに対し複数のクライアントマシンから複数のpgbenchインスタンスを同時に実行することが有用かもしれません。

アダルトレンタルサーバー