pgbench

PostgreSQL 9.1.1文書
前のページ | 巻戻し | 付録 F. 追加で提供されるモジュール | 早送り | 次のページ

# F.26. pgbench

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

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

    transaction type: TPC-B (sort of)
    scaling factor: 10
    query mode: simple
    number of clients: 10
    number of threads: 1
    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)

最初の6行はいくつかの最重要パラメータの設定を表示しています。 次行が完了トランザクション数と予定トランザクション数です（後者は単なるクライアント数とクライアント毎のトランザクション数の積算結果です。） 実行が完了する前に失敗しない限りこれは等しくなります。 (`-T`モードでは、トランザクションの実際の数が表示されます) 最後の2行は、データベースセッションを開始するための時間を含める場合と含めない場合の1秒当たりのトランザクション数を示します。

## F.26.1. 概要

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

    pgbench -i [ other-options ] dbname

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

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

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

    table                   # of rows
    ---------------------------------
    pgbench_branches        1
    pgbench_tellers         10
    pgbench_accounts        100000
    pgbench_history         0

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

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

    pgbench [ options ] dbname

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

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

## F.26.2. pgbench初期化オプション

pgbenchは以下の初期化用のコマンドライン引数を受け付けます。

`-i`

  初期化モードを呼び出すために必要です。

`-F` `fillfactor`

  指定したフィルファクタで`pgbench_accounts`、`pgbench_tellers`、`pgbench_branches`テーブルを作成します。 デフォルトは100です。

`-s` `scale_factor`

  この倍率で生成される行数を積算します。 例えば、`-s 100`は `pgbench_accounts`テーブルに10,000,000行を生成することを意味します。 デフォルトは1です。

## F.26.3. pgbenchベンチマーク用オプション

pgbenchは以下のベンチマーク用コマンドライン引数を受け付けます。

`-c` `clients`

  模擬するクライアント数、つまり、同時に実行されるデータベースセッション数です。 デフォルトは1です。

`-C`

  各クライアントセッションが一度だけ接続を確立するのではなく、各トランザクションが新しい接続を確立します。 これは接続オーバーヘッドを測定する場合に有用です。

`-d`

  デバッグ用出力を表示します。

`-D` `varname``=``value`

  独自スクリプト（後述）で使用される変数を定義します。 複数の`-D`オプションを使用することができます。

`-f` `filename`

  トランザクションスクリプトを`filename`から読み取ります。 詳細は後で説明します。 `-N`、`-S`、`-f`は互いに排他的です。

`-j` `threads`

  pgbench内のワーカスレッド数です。 複数のスレッドを使用することはマルチCPUマシンで有用になります。 各スレッドには管理するクライアントセッションを同じ数与えられますので、クライアント数はスレッド数の倍数でなければなりません。 デフォルトは1です。

`-l`

  各トランザクションで費やした時間をログファイルに書き出します。 後で詳細を説明します。

`-M` `querymode`

  サーバへ問い合わせを送信するために使用するプロトコルです。

  - `simple`: 簡易問い合わせプロトコルを使用します。

  - `extended`: 拡張問い合わせプロトコルを使用します。

  - プリペアドステートメントを伴う拡張問い合わせプロトコルを使用します。

  デフォルトは簡易問い合わせプロトコルです。 （詳しい情報は第46章を参照してください）

`-n`

  試験を実行する前にバキュームを行いません。 `pgbench_accounts`、`pgbench_branches`、`pgbench_history`、 `pgbench_tellers`標準テーブルを含まない独自試験シナリオを実行する場合、このオプションは必要です。

`-N`

  `pgbench_tellers`と`pgbench_branches`を更新しません。 これは両テーブル上の重度の更新の競合を防ぎますが、TPC-Bのような試験ケースを行わなくなります。

`-r`

  ベンチマーク完了後の各コマンドにおけるステートメント毎の平均レイテンシ(クライアントから見た実行時間)を報告します。詳しくは下を参照してください。

`-s` `scale_factor`

  pgbenchの出力で指定した倍率を報告します。 これは組み込みの試験では必要ありません。 正確な倍率が`pgbench_branches`テーブルの行数を数えることで検出されます。 しかし、独自ベンチマーク（`-f`オプション）を試験している場合、このオプションを使用しない限り、倍率は1として報告されます。

`-S`

  TPC-Bのような試験ではなく読み取りのみのトランザクションを実行します。

`-t` `transactions`

  各クライアントが実行するトランザクション数です。 デフォルトは10です。

`-T` `seconds`

  クライアントあたりのトランザクション数を固定で指定するよりも長くテストを実行したい場合、ここに指定した秒数でテストを実行します。 `-t`と`-T`は互いに排他的です。

`-v`

  試験前に4つの標準テーブルすべてをバキュームを行います。 `-n`または`-v`がなければ、pgbenchは`pgbench_tellers`と`pgbench_branches`テーブルをバキュームし、`pgbench_history`内のデータをすべて消去します。

## F.26.4. pgbench共通オプション

pgbenchは以下の共通コマンドライン引数を受け付けます。

`-h` `hostname`

  データベースサーバのホスト

`-p` `port`

  データベースサーバのポート

`-U` `login`

  接続ユーザ名

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

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

1. `BEGIN;`

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

3. `SELECT abalance FROM pgbench_accounts WHERE aid = :aid;`

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

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

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

7. `END;`

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

## F.26.6. 独自スクリプト

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

`\setshell `varname` `command` [ `argument` ... ]`

  `command`シェルコマンドの結果を`varname`変数に設定します。 このコマンドは標準出力を通して整数値を返さなければなりません。

  `argument`は、テキスト定数または任意の型の変数を参照する`:``variablename`とすることができます。 コロンから始まる`argument`を使用したい場合、`argument`の先頭にさらにコロンを付けなければなりません。

  例:

      \setshell variable_to_be_assigned command literal_argument :variable ::literal_starting_with_colon

`\shell `command` [ `argument` ... ]`

  `\setshell`と同じですが、結果は無視されます。

  例:

      \shell command literal_argument :variable ::literal_starting_with_colon

例えば、組込みの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 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;

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

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

`-l`オプションを使用すると、pgbenchは各トランザクションで要した時間をログファイルに書き出します。 ログファイルの名前は`pgbench_log.`nnn``です。 ここで`nnn`はpgbenchプロセスのPIDです。 `-j`オプションが2以上の場合、それぞれ独自のログファイルを持つ複数のワーカスレッドが生成されます。 最初のワーカは標準的な単一ワーカの場合と同じ名前を持つログファイルを使用します。 他のワーカ用の追加のログファイルは`pgbench_log.`nnn`.`mmm``のように命名されます。 ここで`mmm`は1から始まる各ワーカの連番です。

ログの書式は以下の通りです。

    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.26.8. ステートメント毎のレイテンシ

`-r`オプションを付けると、pgbenchは各クライアントにより実行されたトランザクションのステートメント毎の経過時間を収集します。 ベンチマークが終了した後、各値の平均値(各ステートメントのレイテンシと呼びます)が報告されます。

標準スクリプトでは、次のような出力になります。

    starting vacuum...end.
    transaction type: TPC-B (sort of)
    scaling factor: 1
    query mode: simple
    number of clients: 10
    number of threads: 1
    number of transactions per client: 1000
    number of transactions actually processed: 10000/10000
    tps = 618.764555 (including connections establishing)
    tps = 622.977698 (excluding connections establishing)
    statement latencies in milliseconds:
            0.004386        \set nbranches 1 * :scale
            0.001343        \set ntellers 10 * :scale
            0.001212        \set naccounts 100000 * :scale
            0.001310        \setrandom aid 1 :naccounts
            0.001073        \setrandom bid 1 :nbranches
            0.001005        \setrandom tid 1 :ntellers
            0.001078        \setrandom delta -5000 5000
            0.326152        BEGIN;
            0.603376        UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;
            0.454643        SELECT abalance FROM pgbench_accounts WHERE aid = :aid;
            5.528491        UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;
            7.335435        UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;
            0.371851        INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);
            1.212976        END;

複数のスクリプトファイルが定義された場合、平均値はそれぞれのスクリプトファイル毎に分けて報告されます。

ステートメント毎のレイテンシを計算するために必要となる、追加のタイミング情報を収集することは、オーバーヘッドが加わることに注意してください。 これは平均実行速度を遅くし、計測TPSを小さくするでしょう。 低下量はプラットフォームとハードウェアに依存して著しく変わります。 レイテンシの報告を有効にする、有効にしないで平均TPS値を比較することは、タイミング・オーバーヘッドが顕著かどうかを測定するには良い方法です。

## F.26.9. 優れた実践

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

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

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

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

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

前のページ | ホーム | 次のページ
pg_archivecleanup | 上に戻る | pg_buffercache