diff --git a/contrib/pgbench/README.pgbench b/contrib/pgbench/README.pgbench index d062b01e816bb4c121f74ec983325387310da954..de51b2c7bc27235408aa75eb23a7465d02449b12 100644 --- a/contrib/pgbench/README.pgbench +++ b/contrib/pgbench/README.pgbench @@ -1,4 +1,4 @@ -pgbench 1.2 README 2000/1/15 Tatsuo Ishii (t-ishii@sra.co.jp) +pgbench 1.3 README 2001/09/09 Tatsuo Ishii (t-ishii@sra.co.jp) o What is pgbench? @@ -101,6 +101,15 @@ o options (10,000,000) tuples in the accounts table. default is 1. + -U login + Specify db user's login name if it is different from + the Unix login name. + + -P password + Specify the db password. CAUTION: using this option + might be a security hole since ps command will + show the password. Use this for TESTING PURPOSE ONLY. + -n No vacuuming and cleaning the history table prior the test is performed. @@ -113,6 +122,11 @@ o options -S Perform select only transactions instead of TPC-B. + -C + Establish connection for each transaction, rather than + doing it just once at begining of pgbench in the normal + mode. This is usefull to measure the connection overhead. + -d debug option. @@ -139,6 +153,9 @@ Basically it is same as BSD license. See pgbench.c for more details. o History +2001/09/09 + * Add -U, -P, -C options + 2000/1/15 pgbench-1.2 contributed to PostgreSQL * Add -v option diff --git a/contrib/pgbench/README.pgbench_jis b/contrib/pgbench/README.pgbench_jis index 03d466b581a6ded35e4f9a7fbe5e0a6f17724f19..04a5900c65c3d9122c52bb633e8c0963b8084c6f 100644 --- a/contrib/pgbench/README.pgbench_jis +++ b/contrib/pgbench/README.pgbench_jis @@ -1,16 +1,16 @@ -pgbench 1.2 README 2000/1/15 Tatsuo Ishii (t-ishii@sra.co.jp) +pgbench 1.3 README 2001/09/09 Tatsuo Ishii (t-ishii@sra.co.jp) ■pgbench とは? -pgbench は TPC-Bに似たベンチマークテストを行なうプログラムです。今のと -ころ PostgreSQL 専用です。 +pgbench は TPC-Bに似たベンチマークテストを行なうプログラムです.今のと +ころ PostgreSQL 専用です. -pgbench は select/update/insert を含むトランザクションを実行し、全体の +pgbench は select/update/insert を含むトランザクションを実行し,全体の 実行時間と実際に完了したトランザクションの数から 1 秒間に実行できたト -ランザクション数 (tps) を表示します。処理の対象となるテーブルはデフォ -ルトでは 10万タプルのデータを含みます。 +ランザクション数 (tps) を表示します.処理の対象となるテーブルはデフォ +ルトでは 10万タプルのデータを含みます. -実際の表示は以下のような感じです。 +実際の表示は以下のような感じです. number of clients: 4 number of transactions per client: 100 @@ -18,16 +18,16 @@ number of processed transactions: 400/400 tps = 19.875015(including connections establishing) tps = 20.098827(excluding connections establishing) -pgbench は JDBCBench という、もともとは MySQL 用に書かれた JDBC 用のベ -ンチマークプログラムを参考に作成されました。 +pgbench は JDBCBench という,もともとは MySQL 用に書かれた JDBC 用のベ +ンチマークプログラムを参考に作成されました. ■pgbench の特徴 -o C 言語と libpq だけで書かれているので移植性が高く、簡単にインストー -ルできます。 +o C 言語と libpq だけで書かれているので移植性が高く,簡単にインストー +ルできます. o pgbench は libpq の非同期処理機能を使ってマルチユーザ環境をシミュレー -トします。容易に同時接続環境をテストできます。 +トします.容易に同時接続環境をテストできます. ■pgbench のインストール @@ -46,61 +46,72 @@ o pgbench は libpq の非同期処理機能を使ってマルチユーザ環境をシミュレー�����韃矼釿��データベース名] -です。データベース名を省略すると、ユーザ名と同じデータベースを指定した -ものとみなします。データベースは後述の -i オプションを使ってあらかじめ -初期化しておく必要があります。 +です.データベース名を省略すると,ユーザ名と同じデータベースを指定した +ものとみなします.データベースは後述の -i オプションを使ってあらかじめ +初期化しておく必要があります. -pgbench にはいろいろなオプションがあります。 +pgbench にはいろいろなオプションがあります. -h ホスト名 PostgreSQLのデータベースデーモン postmaster の動 - いているホスト名を指定します。省略すると自ホストに Unix domain - socket で接続します。 + いているホスト名を指定します.省略すると自ホストに Unix domain + socket で接続します. --p ポート番号 postmaster の使用するポート番号を指定します。省略すると 5432 - が指定されたものとみなします。 +-p ポート番号 postmaster の使用するポート番号を指定します.省略すると 5432 + が指定されたものとみなします. --c クライアント数 同時実行クライアント数を指定します。省略時は - 1 となります。pgbench は同時実行クライアント毎に - ファイルディスクリプタを使用するので、使用可能 +-c クライアント数 同時実行クライアント数を指定します.省略時は + 1 となります.pgbench は同時実行クライアント毎に + ファイルディスクリプタを使用するので,使用可能 ファイルディスクリプタ数を越えるクライアント数は - 指定できません。使用可能ファイルディスクリプタ数 - は limit や ulimit コマンドで知ることができます。 + 指定できません.使用可能ファイルディスクリプタ数 + は limit や ulimit コマンドで知ることができます. -t トランザクション数 各クライアントが実行するトランザクション数を - 指定します。省略時は 10 となります。 + 指定します.省略時は 10 となります. -s スケーリングファクター - -i オプションと一緒に使用します。 - スケーリングファクターは1以上の整数。スケーリングファ - クターを変えることにより、テストの対象となるテーブルの - 大きさが 10万 x [スケーリングファクター]になります。 - デフォルトのスケーリングファクターは 1 です。 + -i オプションと一緒に使用します. + スケーリングファクターは1以上の整数.スケーリングファ + クターを変えることにより,テストの対象となるテーブルの + 大きさが 10万 x [スケーリングファクター]になります. + デフォルトのスケーリングファクターは 1 です. --v このオプションを指定すると、ベンチマーク開始前に vacuum と - history のクリアを行ないます。-v と -n を省略すると、 - 最小限の vacuum などを行います。すなわち、history の削除、 - と history, branches, history の vacuum を行います。 - これは、vacuum の時間を最小限にしながら、パフォーマンスに - 影響するゴミ掃除を効果的に行います。通常は -v と -n を - 省略することをおすすめします。 +-U login DBユーザのログイン名を指定します. --n このオプションを指定すると、ベンチマーク開始前に vacuum と - history のクリアを行ないません。 +-P password パスワードを指定します.なお,このオプションを使うと, + パスワードをpsコマンドで見られるなど,セキュリティホー + ルになる可能性があるので,テスト用にのみお使い下さい. --S TPC-Bのトランザクションではなく、検索のみのトランザクションを - 実行します。検索スピードを測定したいときに使います。 +-n このオプションを指定すると,ベンチマーク開始前に vacuum と + history のクリアを行ないません. --d デバッグオプション。様々な情報が表示されます。 +-v このオプションを指定すると,ベンチマーク開始前に vacuum と + history のクリアを行ないます.-v と -n を省略すると, + 最小限の vacuum などを行います.すなわち,history の削除, + と history, branches, history の vacuum を行います. + これは,vacuum の時間を最小限にしながら,パフォーマンスに + 影響するゴミ掃除を効果的に行います.通常は -v と -n を + 省略することをおすすめします. + +-S TPC-Bのトランザクションではなく,検索のみのトランザクションを + 実行します.検索スピードを測定したいときに使います. + +-C このオプションを指定すると,最初に確立したコネクション + を使い回すのではなく,各トランザクションごとにDBへの接 + 続を行います.コネクションのオーバーへッドを測定するの + に有効です. + +-d デバッグオプション.様々な情報が表示されます. ■データベースの初期化 -pgbench でベンチマークテストを実施するためには、あらかじめデータベース -を初期化し、テストデータを作る必要があります。 +pgbench でベンチマークテストを実施するためには,あらかじめデータベース +を初期化し,テストデータを作る必要があります. $ pgbench -i [データベース名] -これにより以下のテーブルが作られます(スケーリングファクター == 1 の場合)。 +これにより以下のテーブルが作られます(スケーリングファクター == 1 の場合). *注意* 同じ名前のテーブルがあると削除されてしまうのでご注意下さい!! @@ -112,9 +123,9 @@ tellers 10 accounts 100000 history 0 -スケーリングファクターを 10,100,1000 などに変更すると、上記タプル数は -それに応じて10倍、100倍、1000倍になります。たとえば、スケーリングファ -クターを 10 とすると、 +スケーリングファクターを 10,100,1000 などに変更すると,上記タプル数は +それに応じて10倍,100倍,1000倍になります.たとえば,スケーリングファ +クターを 10 とすると, テーブル名 タプル数 ------------------------- @@ -123,28 +134,28 @@ tellers 100 accounts 1000000 history 0 -になります。 +になります. ■「トランザクション」の定義 -pgbench では、以下のシーケンスを全部完了して1トランザクションと数えて -います。 +pgbench では,以下のシーケンスを全部完了して1トランザクションと数えて +います. (1) begin; (2) update accounts set abalance = abalance + :delta where aid = :aid; - ここで、:deltaは1から1000までの値を取る乱数、:aid は 1から100000まで - の値を取る乱数です。以下、乱数の値はそれぞれこのトランザクションの - 中では同じ値を使います。 + ここで,:deltaは1から1000までの値を取る乱数,:aid は 1から100000まで + の値を取る乱数です.以下,乱数の値はそれぞれこのトランザクションの + 中では同じ値を使います. (3) select abalance from accounts where aid = :aid; - ここでは1件だけ検索されます。 + ここでは1件だけ検索されます. (4) update tellers set tbalance = tbalance + :delta where tid = :tid; - ここで :tid は 1から10の間の値をとる乱数です。 + ここで :tid は 1から10の間の値をとる乱数です. (5) update branches set bbalance = bbalance + :delta where bid = :bid; - ここで :bid は 1 から[スケリングファクター]の間の値を取る乱数です。 + ここで :bid は 1 から[スケリングファクター]の間の値を取る乱数です. (6) insert into history(tid,bid,aid,delta) values(:tid,:bid,:aid,:delta); @@ -152,13 +163,16 @@ pgbench では、以下のシーケンスを全部完了して1トランザクションと数えて����■作者とライセンス条件 -pgbench は石井 達夫によって書かれました。ライセンス条件は pgbench.c の -冒頭に書いてあります。この条件を守る限り無償で利用し、また自由に再配付 -できます。 +pgbench は石井 達夫によって書かれました.ライセンス条件は pgbench.c の +冒頭に書いてあります.この条件を守る限り無償で利用し,また自由に再配付 +できます. ■改定履歴 -2000/1/15 pgbench-1.2 は PostgreSQL に contribute されました。 +2001/09/09 + * PostgreSQL 7.2用に,-U, -P, -C オプションを追加しました. + +2000/1/15 pgbench-1.2 は PostgreSQL に contribute されました. * -v オプション追加 1999/09/29 pgbench-1.1 リリース diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c index eadc57bdf3251b7aac9f496834270b9c51969abb..6cb15bd2cab8ec72efcab099a6de498138f0c902 100644 --- a/contrib/pgbench/pgbench.c +++ b/contrib/pgbench/pgbench.c @@ -1,5 +1,5 @@ /* - * $Header: /cvsroot/pgsql/contrib/pgbench/pgbench.c,v 1.9 2001/08/01 01:08:17 ishii Exp $ + * $Header: /cvsroot/pgsql/contrib/pgbench/pgbench.c,v 1.10 2001/09/09 03:15:56 ishii Exp $ * * pgbench: a simple TPC-B like benchmark program for PostgreSQL * written by Tatsuo Ishii @@ -67,6 +67,16 @@ int tps = 1; int remains; /* number of remained clients */ +int is_connect; /* establish connection for each transactoin */ + +char *pghost = ""; +char *pgport = NULL; +char *pgoptions = NULL; +char *pgtty = NULL; +char *login = NULL; +char *pwd = NULL; +char *dbName; + typedef struct { PGconn *con; /* connection handle to DB */ @@ -85,8 +95,8 @@ typedef struct static void usage() { - fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-n][-v][-S][-d][dbname]\n"); - fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor][-d][dbname]\n"); + fprintf(stderr, "usage: pgbench [-h hostname][-p port][-c nclients][-t ntransactions][-s scaling_factor][-n][-C][-v][-S][-U login][-P password][-d][dbname]\n"); + fprintf(stderr, "(initialize mode): pgbench -i [-h hostname][-p port][-s scaling_factor][-U login][-P password][-d][dbname]\n"); } /* random number generator */ @@ -96,6 +106,34 @@ getrand(int min, int max) return (min + (int) (max * 1.0 * rand() / (RAND_MAX + 1.0))); } +/* set up a connection to the backend */ +static PGconn *doConnect() +{ + PGconn *con; + + con = PQsetdbLogin(pghost, pgport, pgoptions, pgtty, dbName, + login, pwd); + if (con == NULL) + { + fprintf(stderr, "Connection to database '%s' failed.\n", dbName); + fprintf(stderr, "Memory allocatin problem?\n"); + return(NULL); + } + + if (PQstatus(con) == CONNECTION_BAD) + { + fprintf(stderr, "Connection to database '%s' failed.\n", dbName); + + if (PQerrorMessage(con)) + fprintf(stderr, "%s", PQerrorMessage(con)); + else + fprintf(stderr, "No explanation from the backend\n"); + + return(NULL); + } + return (con); +} + /* throw away response from backend */ static void discard_response(CState * state) @@ -110,6 +148,7 @@ discard_response(CState * state) } while (res); } +/* check to see if the SQL result was good */ static int check(CState * state, PGresult *res, int n, int good) { @@ -123,7 +162,7 @@ check(CState * state, PGresult *res, int n, int good) st->con = NULL; return (-1); } - return (0); + return (0); /* OK */ } /* process a transaction */ @@ -201,11 +240,20 @@ doOne(CState * state, int n, int debug) PQclear(res); discard_response(st); + if (is_connect) + { + PQfinish(st->con); + st->con = NULL; + } + if (++st->cnt >= nxacts) { remains--; /* I've done */ - PQfinish(st->con); - st->con = NULL; + if (st->con != NULL) + { + PQfinish(st->con); + st->con = NULL; + } return; } break; @@ -217,6 +265,19 @@ doOne(CState * state, int n, int debug) st->state = 0; } + if (st->con == NULL) + { + if ((st->con = doConnect()) == NULL) + { + fprintf(stderr, "Client %d aborted in establishing connection.\n", + n); + remains--; /* I've aborted */ + PQfinish(st->con); + st->con = NULL; + return; + } + } + switch (st->state) { case 0: /* about to start */ @@ -295,11 +356,20 @@ doSelectOnly(CState * state, int n, int debug) PQclear(res); discard_response(st); + if (is_connect) + { + PQfinish(st->con); + st->con = NULL; + } + if (++st->cnt >= nxacts) { remains--; /* I've done */ - PQfinish(st->con); - st->con = NULL; + if (st->con != NULL) + { + PQfinish(st->con); + st->con = NULL; + } return; } break; @@ -311,6 +381,19 @@ doSelectOnly(CState * state, int n, int debug) st->state = 0; } + if (st->con == NULL) + { + if ((st->con = doConnect()) == NULL) + { + fprintf(stderr, "Client %d aborted in establishing connection.\n", + n); + remains--; /* I've aborted */ + PQfinish(st->con); + st->con = NULL; + return; + } + } + switch (st->state) { case 0: @@ -349,7 +432,7 @@ disconnect_all(CState * state) /* create tables and setup data */ static void -init(char *pghost, char *pgport, char *dbName) +init() { PGconn *con; PGresult *res; @@ -366,13 +449,8 @@ init(char *pghost, char *pgport, char *dbName) int i; - con = PQsetdb(pghost, pgport, NULL, NULL, dbName); - if (PQstatus(con) == CONNECTION_BAD) - { - fprintf(stderr, "Connection to database '%s' on %s failed.\n", dbName, pghost); - fprintf(stderr, "%s", PQerrorMessage(con)); - exit(1); - } + if ((con = doConnect()) == NULL) + exit(1); for (i = 0; i < (sizeof(DDLs) / sizeof(char *)); i++) { @@ -524,6 +602,7 @@ printResults( printf("tps = %f(excluding connections establishing)\n", t2); } + int main(int argc, char **argv) { @@ -532,9 +611,6 @@ main(int argc, char **argv) opterr, optopt; int c; - char *pghost = NULL; - char *pgport = NULL; - char *dbName; int is_init_mode = 0; /* initialize mode? */ int is_no_vacuum = 0; /* no vacuum at all before * testing? */ @@ -564,7 +640,7 @@ main(int argc, char **argv) PGconn *con; PGresult *res; - while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:S")) != EOF) + while ((c = getopt(argc, argv, "ih:nvp:dc:t:s:U:P:CS")) != EOF) { switch (c) { @@ -615,6 +691,9 @@ main(int argc, char **argv) } #endif /* #ifndef __CYGWIN__ */ break; + case 'C': + is_connect = 1; + break; case 's': tps = atoi(optarg); if (tps <= 0) @@ -631,6 +710,12 @@ main(int argc, char **argv) exit(1); } break; + case 'U': + login = optarg; + break; + case 'P': + pwd = optarg; + break; default: usage(); exit(1); @@ -649,7 +734,7 @@ main(int argc, char **argv) if (is_init_mode) { - init(pghost, pgport, dbName); + init(); exit(0); } @@ -662,7 +747,10 @@ main(int argc, char **argv) } /* opening connection... */ - con = PQsetdb(pghost, pgport, NULL, NULL, dbName); + con = doConnect(); + if (con == NULL) + exit(1); + if (PQstatus(con) == CONNECTION_BAD) { fprintf(stderr, "Connection to database '%s' failed.\n", dbName); @@ -746,16 +834,14 @@ main(int argc, char **argv) /* get start up time */ gettimeofday(&tv1, 0); - /* make connections to the database */ - for (i = 0; i < nclients; i++) + if (is_connect == 0) { - state[i].con = PQsetdb(pghost, pgport, NULL, NULL, dbName); - if (PQstatus(state[i].con) == CONNECTION_BAD) - { - fprintf(stderr, "Connection to database '%s' failed.\n", dbName); - fprintf(stderr, "%s", PQerrorMessage(state[i].con)); - exit(1); - } + /* make connections to the database */ + for (i = 0; i < nclients; i++) + { + if ((state[i].con = doConnect()) == NULL) + exit(1); + } } /* time after connections set up */