* A simple benchmark program for PostgreSQL
* Originally written by Tatsuo Ishii and enhanced by many contributors.
*
- * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.97 2010/02/26 02:00:32 momjian Exp $
+ * $PostgreSQL: pgsql/contrib/pgbench/pgbench.c,v 1.98 2010/03/23 01:29:22 itagaki Exp $
* Copyright (c) 2000-2010, PostgreSQL Global Development Group
* ALL RIGHTS RESERVED;
*
#define ntellers 10
#define naccounts 100000
-FILE *LOGFILE = NULL;
-
bool use_log; /* log transaction latencies to a file */
-
-int is_connect; /* establish connection for each transaction */
+bool is_connect; /* establish connection for each transaction */
+int main_pid; /* main process id used in log filename */
char *pghost = "";
char *pgport = "";
*/
typedef struct
{
+ int tid; /* thread id */
pthread_t thread; /* thread handle */
CState *state; /* array of CState */
int nstate; /* length of state[] */
/* return false iff client should be disconnected */
static bool
-doCustom(CState *st, instr_time *conn_time)
+doCustom(CState *st, instr_time *conn_time, FILE *logfile)
{
PGresult *res;
Command **commands;
/*
* transaction finished: record the time it took in the log
*/
- if (use_log && commands[st->state + 1] == NULL)
+ if (logfile && commands[st->state + 1] == NULL)
{
instr_time now;
instr_time diff;
#ifndef WIN32
/* This is more than we really ought to know about instr_time */
- fprintf(LOGFILE, "%d %d %.0f %d %ld %ld\n",
+ fprintf(logfile, "%d %d %.0f %d %ld %ld\n",
st->id, st->cnt, usec, st->use_file,
(long) now.tv_sec, (long) now.tv_usec);
#else
/* On Windows, instr_time doesn't provide a timestamp anyway */
- fprintf(LOGFILE, "%d %d %.0f %d 0 0\n",
+ fprintf(logfile, "%d %d %.0f %d 0 0\n",
st->id, st->cnt, usec, st->use_file);
#endif
}
INSTR_TIME_ACCUM_DIFF(*conn_time, end, start);
}
- if (use_log && st->state == 0)
+ if (logfile && st->state == 0)
INSTR_TIME_SET_CURRENT(st->txn_begin);
if (commands[st->state]->type == SQL_COMMAND)
}
break;
case 'C':
- is_connect = 1;
+ is_connect = true;
break;
case 's':
scale_given = true;
exit(1);
}
+ /*
+ * save main process id in the global variable because process id will be
+ * changed after fork.
+ */
+ main_pid = (int) getpid();
+
if (nclients > 1)
{
state = (CState *) realloc(state, sizeof(CState) * nclients);
}
}
- if (use_log)
- {
- char logpath[64];
-
- snprintf(logpath, 64, "pgbench_log.%d", (int) getpid());
- LOGFILE = fopen(logpath, "w");
-
- if (LOGFILE == NULL)
- {
- fprintf(stderr, "Couldn't open logfile \"%s\": %s", logpath, strerror(errno));
- exit(1);
- }
- }
-
if (debug)
{
if (duration <= 0)
threads = (TState *) malloc(sizeof(TState) * nthreads);
for (i = 0; i < nthreads; i++)
{
+ threads[i].tid = i;
threads[i].state = &state[nclients / nthreads * i];
threads[i].nstate = nclients / nthreads;
INSTR_TIME_SET_CURRENT(threads[i].start_time);
INSTR_TIME_SET_CURRENT(total_time);
INSTR_TIME_SUBTRACT(total_time, start_time);
printResults(ttype, total_xacts, nclients, nthreads, total_time, conn_total_time);
- if (LOGFILE)
- fclose(LOGFILE);
return 0;
}
TState *thread = (TState *) arg;
CState *state = thread->state;
TResult *result;
+ FILE *logfile = NULL; /* per-thread log file */
instr_time start,
end;
int nstate = thread->nstate;
result = malloc(sizeof(TResult));
INSTR_TIME_SET_ZERO(result->conn_time);
- if (is_connect == 0)
+ /* open log file if requested */
+ if (use_log)
+ {
+ char logpath[64];
+
+ if (thread->tid == 0)
+ snprintf(logpath, sizeof(logpath), "pgbench_log.%d", main_pid);
+ else
+ snprintf(logpath, sizeof(logpath), "pgbench_log.%d.%d", main_pid, thread->tid);
+ logfile = fopen(logpath, "w");
+
+ if (logfile == NULL)
+ {
+ fprintf(stderr, "Couldn't open logfile \"%s\": %s", logpath, strerror(errno));
+ goto done;
+ }
+ }
+
+ if (!is_connect)
{
/* make connections to the database */
for (i = 0; i < nstate; i++)
int prev_ecnt = st->ecnt;
st->use_file = getrand(0, num_files - 1);
- if (!doCustom(st, &result->conn_time))
+ if (!doCustom(st, &result->conn_time, logfile))
remains--; /* I've aborted */
if (st->ecnt > prev_ecnt && commands[st->state]->type == META_COMMAND)
if (st->con && (FD_ISSET(PQsocket(st->con), &input_mask)
|| commands[st->state]->type == META_COMMAND))
{
- if (!doCustom(st, &result->conn_time))
+ if (!doCustom(st, &result->conn_time, logfile))
remains--; /* I've aborted */
}
result->xacts += state[i].cnt;
INSTR_TIME_SET_CURRENT(end);
INSTR_TIME_ACCUM_DIFF(result->conn_time, end, start);
+ if (logfile)
+ fclose(logfile);
return result;
}
-
-
-
-
pgbench
-
-
-
-
-
pgbench is a simple program for running benchmark
- tests on
PostgreSQL>. It runs the same sequence of SQL
- commands over and over, possibly in multiple concurrent database sessions,
- and then calculates the average transaction rate (transactions per second).
- By default,
pgbench tests a scenario that is
- loosely based on TPC-B, involving five SELECT>,
- UPDATE>, and INSERT> commands per transaction.
- However, it is easy to test other cases by writing your own transaction
- script files.
-
-
- Typical output from pgbench looks like:
-
-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)
-
-
- The first six lines report some of the most important parameter
- settings. The next line reports the number of transactions completed
- and intended (the latter being just the product of number of clients
- and number of transactions per client); these will be equal unless the run
- failed before completion. The last two lines report the TPS rate,
- figured with and without counting the time to start database sessions.
-
-
-
-
Overview
-
- The default TPC-B-like transaction test requires specific tables to be
- set up beforehand.
pgbench> should be invoked with
- the -i> (initialize) option to create and populate these
- tables. (When you are testing a custom script, you don't need this
- step, but will instead need to do whatever setup your test needs.)
- Initialization looks like:
-
-pgbench -i other-options> dbname>
-
-
- where dbname> is the name of the already-created
- database to test in. (You may also need -h>,
- -p>, and/or -U> options to specify how to
- connect to the database server.)
-
-
-
- pgbench -i> creates four tables pgbench_accounts>,
- pgbench_branches>, pgbench_history>, and
- pgbench_tellers>,
- destroying any existing tables of these names.
- Be very careful to use another database if you have tables having these
- names!
-
-
-
- At the default scale factor> of 1, the tables initially
- contain this many rows:
-
-table # of rows
----------------------------------
-pgbench_branches 1
-pgbench_tellers 10
-pgbench_accounts 100000
-pgbench_history 0
-
- You can (and, for most purposes, probably should) increase the number
- of rows by using the -s> (scale factor) option. The
- -F> (fillfactor) option might also be used at this point.
-
-
- Once you have done the necessary setup, you can run your benchmark
- with a command that doesn't include -i>, that is
-
-pgbench options> dbname>
-
-
- In nearly all cases, you'll need some options to make a useful test.
- The most important options are -c> (number of clients),
- -t> (number of transactions), -T> (time limit),
- and -f> (specify a custom script file).
- See below for a full list.
-
-
- shows options that are used
- during database initialization, while
- shows options that are used
- while running benchmarks, and
- shows options that are useful
- in both cases.
-
-
-
-
pgbench initialization options
-
-
- |
- Option
- Description
-
-
-
-
- |
- -i
-
- Required to invoke initialization mode.
-
-
- |
- -s scale_factor>
-
- Multiply the number of rows generated by the scale factor.
- For example, -s 100> will create 10,000,000 rows
- in the pgbench_accounts> table. Default is 1.
-
-
- |
- -F fillfactor>
-
- Create the pgbench_accounts>,
- pgbench_tellers> and
- pgbench_branches> tables with the given fillfactor.
- Default is 100.
-
-
-
-
-
-
-
-
pgbench benchmarking options
-
-
- |
- Option
- Description
-
-
-
-
- |
- -c clients>
-
- Number of clients simulated, that is, number of concurrent database
- sessions. Default is 1.
-
-
- |
- -j threads>
-
- Number of worker threads within
pgbench.
- Using more than one thread can be helpful on multi-CPU machines.
- The number of clients must be a multiple of the number of threads,
- since each thread is given the same number of client sessions to manage.
- Default is 1.
-
-
- |
- -t transactions>
-
- Number of transactions each client runs. Default is 10.
-
-
- |
- -T seconds>
-
- Run the test for this many seconds, rather than a fixed number of
- transactions per client. -t and
- -T are mutually exclusive.
-
-
- |
- -M querymode>
-
- Protocol to use for submitting queries to the server:
-
-
-
simple>: use simple query protocol.
-
-
-
extended>: use extended query protocol.
-
-
-
prepared>: use extended query protocol with prepared statements.
-
-
- The default is simple query protocol. (See
- for more information.)
-
-
- |
- -N
-
- Do not update pgbench_tellers> and
- pgbench_branches>.
- This will avoid update contention on these tables, but
- it makes the test case even less like TPC-B.
-
-
- |
- -S
-
- Perform select-only transactions instead of TPC-B-like test.
-
-
- |
- -f filename>
-
- Read transaction script from filename>.
- See below for details.
- -N, -S, and -f
- are mutually exclusive.
-
-
- |
- -n
-
- Perform no vacuuming before running the test.
- This option is necessary>
- if you are running a custom test scenario that does not include
- the standard tables pgbench_accounts>,
- pgbench_branches>, pgbench_history>, and
- pgbench_tellers>.
-
-
- |
- -v
-
- Vacuum all four standard tables before running the test.
- With neither -n> nor -v>, pgbench will vacuum the
- pgbench_tellers> and pgbench_branches>
- tables, and will truncate pgbench_history>.
-
-
- |
- -D varname>=>value>
-
- Define a variable for use by a custom script (see below).
- Multiple -D> options are allowed.
-
-
- |
- -C
-
- Establish a new connection for each transaction, rather than
- doing it just once per client session.
- This is useful to measure the connection overhead.
-
-
- |
- -l
-
- Write the time taken by each transaction to a logfile.
- See below for details.
-
-
- |
- -s scale_factor>
-
- Report the specified scale factor in
pgbench>'s
- output. With the built-in tests, this is not necessary; the
- correct scale factor will be detected by counting the number of
- rows in the pgbench_branches> table. However, when testing
- custom benchmarks (-f> option), the scale factor
- will be reported as 1 unless this option is used.
-
-
- |
- -d
-
- Print debugging output.
-
-
-
-
-
-
-
-
-
- |
- Option
- Description
-
-
-
-
- |
- -h hostname>
- database server's host
-
- |
- -p port>
- database server's port
-
- |
- -U login>
- username to connect as
-
-
-
-
-
-
-
-
What is the transaction> actually performed in pgbench?
-
- The default transaction script issues seven commands per transaction:
-
-
-
-
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);
-
-
- If you specify -N>, steps 4 and 5 aren't included in the
- transaction. If you specify -S>, only the SELECT> is
- issued.
-
-
-
-
-
Custom Scripts
-
-
pgbench has support for running custom
- benchmark scenarios by replacing the default transaction script
- (described above) with a transaction script read from a file
- (-f option). In this case a transaction>
- counts as one execution of a script file. You can even specify
- multiple scripts (multiple -f options), in which
- case a random one of the scripts is chosen each time a client session
- starts a new transaction.
-
-
- The format of a script file is one SQL command per line; multi-line
- SQL commands are not supported. Empty lines and lines beginning with
- --> are ignored. Script file lines can also be
-
meta commands>, which are interpreted by pgbench>
- itself, as described below.
-
-
- There is a simple variable-substitution facility for script files.
- Variables can be set by the command-line -D> option,
- explained above, or by the meta commands explained below.
- In addition to any variables preset by -D> command-line options,
- the variable scale> is preset to the current scale factor.
- Once set, a variable's
- value can be inserted into a SQL command by writing
- :>variablename>. When running more than
- one client session, each session has its own set of variables.
-
-
- Script file meta commands begin with a backslash (\>).
- Arguments to a meta command are separated by white space.
- These meta commands are supported:
-
-
-
-
-
- \set varname> operand1> [ operator> operand2> ]
-
-
-
- Sets variable varname> to a calculated integer value.
- Each operand> is either an integer constant or a
- :>variablename> reference to a variable
- having an integer value. The operator> can be
- +>, ->, *>, or />.
-
-
- Example:
-\set ntellers 10 * :scale
-
-
-
-
-
-
-
- \setrandom varname> min> max>
-
-
-
- Sets variable varname> to a random integer value
- between the limits min> and max> inclusive.
- Each limit can be either an integer constant or a
- :>variablename> reference to a variable
- having an integer value.
-
-
- Example:
-\setrandom aid 1 :naccounts
-
-
-
-
-
-
-
- \sleep number> [ us | ms | s ]
-
-
-
- Causes script execution to sleep for the specified duration in
- microseconds (us>), milliseconds (ms>) or seconds
- (s>). If the unit is omitted then seconds are the default.
- number> can be either an integer constant or a
- :>variablename> reference to a variable
- having an integer value.
-
-
- Example:
-\sleep 10 ms
-
-
-
-
-
-
-
- \setshell varname> command> [ argument> ... ]
-
-
-
- Sets variable varname> to the result of the shell command
- command>. The command must return an integer value
- through its standard output.
-
-
- argument> can be either a text constant or a
- :>variablename> reference to a variable of
- any types. If you want to use argument> starting with
- colons, you need to add an additional colon at the beginning of
- argument>.
-
-
- Example:
-\setshell variable_to_be_assigned command literal_argument :variable ::literal_starting_with_colon
-
-
-
-
-
-
-
- \shell command> [ argument> ... ]
-
-
-
- Same as \setshell, but the result is ignored.
-
-
- Example:
-\shell command literal_argument :variable ::literal_starting_with_colon
-
-
-
-
-
-
- As an example, the full definition of the built-in TPC-B-like
- transaction is:
-
-\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;
-
-
- This script allows each iteration of the transaction to reference
- different, randomly-chosen rows. (This example also shows why it's
- important for each client session to have its own variables —
- otherwise they'd not be independently touching different rows.)
-
-
-
-
-
-
Per-transaction logging
-
- With the
-l> option, pgbench> writes the time
- taken by each transaction to a logfile. The logfile will be named
- pgbench_log.nnn>, where
- nnn> is the PID of the pgbench process.
- The format of the log is:
-
- client_id> transaction_no> time> file_no> time_epoch> time_us>
-
-
- where time> is the elapsed transaction time in microseconds,
- file_no> identifies which script file was used
- (useful when multiple scripts were specified with -f>),
- and time_epoch>/time_us> are a
- UNIX epoch format timestamp and an offset
- in microseconds (suitable for creating a ISO 8601
- timestamp with fractional seconds) showing when
- the transaction completed.
-
-
- Here are example outputs:
- 0 199 2241 0 1175850568 995598
- 0 200 2465 0 1175850568 998079
- 0 201 2513 0 1175850569 608
- 0 202 2038 0 1175850569 2663
-
-
-
-
-
-
Good Practices
-
- It is very easy to use
pgbench> to produce completely
- meaningless numbers. Here are some guidelines to help you get useful
- results.
-
-
- In the first place, never> believe any test that runs
- for only a few seconds. Use the -t> or -T> option
- to make the run last at least a few minutes, so as to average out noise.
- In some cases you could need hours to get numbers that are reproducible.
- It's a good idea to try the test run a few times, to find out if your
- numbers are reproducible or not.
-
-
- For the default TPC-B-like test scenario, the initialization scale factor
- (-s>) should be at least as large as the largest number of
- clients you intend to test (-c>); else you'll mostly be
- measuring update contention. There are only -s> rows in
- the pgbench_branches> table, and every transaction wants to
- update one of them, so -c> values in excess of -s>
- will undoubtedly result in lots of transactions blocked waiting for
- other transactions.
-
-
- The default test scenario is also quite sensitive to how long it's been
- since the tables were initialized: accumulation of dead rows and dead space
- in the tables changes the results. To understand the results you must keep
- track of the total number of updates and when vacuuming happens. If
- autovacuum is enabled it can result in unpredictable changes in measured
- performance.
-
-
- A limitation of
pgbench> is that it can itself become
- the bottleneck when trying to test a large number of client sessions.
- This can be alleviated by running
pgbench> on a different
- machine from the database server, although low network latency will be
- essential. It might even be useful to run several
pgbench>
- instances concurrently, on several client machines, against the same
- database server.
-
-
-
-
+\r
+\r
+\r
+
pgbench\r
+\r
+ \r
+ \r
+\r
+
pgbench is a simple program for running benchmark
\r
+ tests on
PostgreSQL>. It runs the same sequence of SQL\r
+ commands over and over, possibly in multiple concurrent database sessions,\r
+ and then calculates the average transaction rate (transactions per second).\r
+ By default,
pgbench tests a scenario that is
\r
+ loosely based on TPC-B, involving five SELECT>,\r
+ UPDATE>, and INSERT> commands per transaction.\r
+ However, it is easy to test other cases by writing your own transaction\r
+ script files.\r
+ \r
+\r
+ Typical output from pgbench looks like:\r
+\r
+transaction type: TPC-B (sort of)\r
+scaling factor: 10\r
+query mode: simple\r
+number of clients: 10\r
+number of threads: 1\r
+number of transactions per client: 1000\r
+number of transactions actually processed: 10000/10000\r
+tps = 85.184871 (including connections establishing)\r
+tps = 85.296346 (excluding connections establishing)\r
+ \r
+\r
+ The first six lines report some of the most important parameter\r
+ settings. The next line reports the number of transactions completed\r
+ and intended (the latter being just the product of number of clients\r
+ and number of transactions per client); these will be equal unless the run\r
+ failed before completion. The last two lines report the TPS rate,\r
+ figured with and without counting the time to start database sessions.\r
+ \r
+\r
+ \r
+
Overview\r
+\r
+ The default TPC-B-like transaction test requires specific tables to be\r
+ set up beforehand.
pgbench> should be invoked with\r
+ the -i> (initialize) option to create and populate these\r
+ tables. (When you are testing a custom script, you don't need this\r
+ step, but will instead need to do whatever setup your test needs.)\r
+ Initialization looks like:\r
+\r
+pgbench -i other-options> dbname>\r
+ \r
+\r
+ where dbname> is the name of the already-created\r
+ database to test in. (You may also need -h>,\r
+ -p>, and/or -U> options to specify how to\r
+ connect to the database server.)\r
+ \r
+\r
+ \r
+ pgbench -i> creates four tables pgbench_accounts>,\r
+ pgbench_branches>, pgbench_history>, and\r
+ pgbench_tellers>,\r
+ destroying any existing tables of these names.\r
+ Be very careful to use another database if you have tables having these\r
+ names!\r
+ \r
+ \r
+\r
+ At the default scale factor> of 1, the tables initially\r
+ contain this many rows:\r
+ \r
+table # of rows\r
+---------------------------------\r
+pgbench_branches 1\r
+pgbench_tellers 10\r
+pgbench_accounts 100000\r
+pgbench_history 0\r
+ \r
+ You can (and, for most purposes, probably should) increase the number\r
+ of rows by using the -s> (scale factor) option. The\r
+ -F> (fillfactor) option might also be used at this point.\r
+ \r
+\r
+ Once you have done the necessary setup, you can run your benchmark\r
+ with a command that doesn't include -i>, that is\r
+\r
+pgbench options> dbname>\r
+ \r
+\r
+ In nearly all cases, you'll need some options to make a useful test.\r
+ The most important options are -c> (number of clients),\r
+ -t> (number of transactions), -T> (time limit),\r
+ and -f> (specify a custom script file).\r
+ See below for a full list.\r
+ \r
+\r
+ shows options that are used\r
+ during database initialization, while\r
+ shows options that are used\r
+ while running benchmarks, and\r
+ shows options that are useful\r
+ in both cases.\r
+ \r
+\r
+
\r
+
pgbench initialization options\r
+ \r
+
\r
+ \r
+ Option\r
+ Description\r
+ \r
+
\r
+\r
+
\r
+ \r
+ -i\r
+ \r
+ Required to invoke initialization mode.\r
+ \r
+ \r
+ \r
+ -s scale_factor>\r
+ \r
+ Multiply the number of rows generated by the scale factor.\r
+ For example, -s 100> will create 10,000,000 rows\r
+ in the pgbench_accounts> table. Default is 1.\r
+ \r
+ \r
+ \r
+ -F fillfactor>\r
+ \r
+ Create the pgbench_accounts>,\r
+ pgbench_tellers> and\r
+ pgbench_branches> tables with the given fillfactor.\r
+ Default is 100.\r
+ \r
+ \r
+
\r
+ \r
+
\r
+\r
+
\r
+
pgbench benchmarking options\r
+ \r
+
\r
+ \r
+ Option\r
+ Description\r
+ \r
+
\r
+\r
+
\r
+ \r
+ -c clients>\r
+ \r
+ Number of clients simulated, that is, number of concurrent database\r
+ sessions. Default is 1.\r
+ \r
+ \r
+ \r
+ -j threads>\r
+ \r
+ Number of worker threads within
pgbench.
\r
+ Using more than one thread can be helpful on multi-CPU machines.\r
+ The number of clients must be a multiple of the number of threads,\r
+ since each thread is given the same number of client sessions to manage.\r
+ Default is 1.\r
+ \r
+ \r
+ \r
+ -t transactions>\r
+ \r
+ Number of transactions each client runs. Default is 10.\r
+ \r
+ \r
+ \r
+ -T seconds>\r
+ \r
+ Run the test for this many seconds, rather than a fixed number of\r
+ transactions per client. -t and\r
+ -T are mutually exclusive.\r
+ \r
+ \r
+ \r
+ -M querymode>\r
+ \r
+ Protocol to use for submitting queries to the server:\r
+ \r
+ \r
+
simple>: use simple query protocol.\r
+ \r
+ \r
+
extended>: use extended query protocol.\r
+ \r
+ \r
+
prepared>: use extended query protocol with prepared statements.\r
+ \r
+ \r
+ The default is simple query protocol. (See \r
+ for more information.)\r
+ \r
+ \r
+ \r
+ -N\r
+ \r
+ Do not update pgbench_tellers> and\r
+ pgbench_branches>.\r
+ This will avoid update contention on these tables, but\r
+ it makes the test case even less like TPC-B.\r
+ \r
+ \r
+ \r
+ -S\r
+ \r
+ Perform select-only transactions instead of TPC-B-like test.\r
+ \r
+ \r
+ \r
+ -f filename>\r
+ \r
+ Read transaction script from filename>.\r
+ See below for details.\r
+ -N, -S, and -f\r
+ are mutually exclusive.\r
+ \r
+ \r
+ \r
+ -n\r
+ \r
+ Perform no vacuuming before running the test.\r
+ This option is necessary>\r
+ if you are running a custom test scenario that does not include\r
+ the standard tables pgbench_accounts>,\r
+ pgbench_branches>, pgbench_history>, and\r
+ pgbench_tellers>.\r
+ \r
+ \r
+ \r
+ -v\r
+ \r
+ Vacuum all four standard tables before running the test.\r
+ With neither -n> nor -v>, pgbench will vacuum the\r
+ pgbench_tellers> and pgbench_branches>\r
+ tables, and will truncate pgbench_history>.\r
+ \r
+ \r
+ \r
+ -D varname>=>value>\r
+ \r
+ Define a variable for use by a custom script (see below).\r
+ Multiple -D> options are allowed.\r
+ \r
+ \r
+ \r
+ -C\r
+ \r
+ Establish a new connection for each transaction, rather than\r
+ doing it just once per client session.\r
+ This is useful to measure the connection overhead.\r
+ \r
+ \r
+ \r
+ -l\r
+ \r
+ Write the time taken by each transaction to a logfile.\r
+ See below for details.\r
+ \r
+ \r
+ \r
+ -s scale_factor>\r
+ \r
+ Report the specified scale factor in
pgbench>'s\r
+ output. With the built-in tests, this is not necessary; the\r
+ correct scale factor will be detected by counting the number of\r
+ rows in the pgbench_branches> table. However, when testing\r
+ custom benchmarks (-f> option), the scale factor\r
+ will be reported as 1 unless this option is used.\r
+ \r
+ \r
+ \r
+ -d\r
+ \r
+ Print debugging output.\r
+ \r
+ \r
+
\r
+ \r
+
\r
+\r
+
\r
+
pgbench common options\r
+ \r
+
\r
+ \r
+ Option\r
+ Description\r
+ \r
+
\r
+\r
+
\r
+ \r
+ -h hostname>\r
+ database server's host\r
+ \r
+ \r
+ -p port>\r
+ database server's port\r
+ \r
+ \r
+ -U login>\r
+ username to connect as\r
+ \r
+
\r
+ \r
+
\r
+ \r
+\r
+ \r
+
What is the transaction> actually performed in pgbench?
\r
+\r
+ The default transaction script issues seven commands per transaction:\r
+ \r
+\r
+ \r
+
UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\r
+
SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\r
+
UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\r
+
UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\r
+
INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\r
+ \r
+\r
+ If you specify -N>, steps 4 and 5 aren't included in the\r
+ transaction. If you specify -S>, only the SELECT> is\r
+ issued.\r
+ \r
+ \r
+\r
+ \r
+
Custom Scripts\r
+\r
+
pgbench has support for running custom
\r
+ benchmark scenarios by replacing the default transaction script\r
+ (described above) with a transaction script read from a file\r
+ (-f option). In this case a transaction>\r
+ counts as one execution of a script file. You can even specify\r
+ multiple scripts (multiple -f options), in which\r
+ case a random one of the scripts is chosen each time a client session\r
+ starts a new transaction.\r
+ \r
+\r
+ The format of a script file is one SQL command per line; multi-line\r
+ SQL commands are not supported. Empty lines and lines beginning with\r
+ --> are ignored. Script file lines can also be\r
+
meta commands>, which are interpreted by pgbench>\r
+ itself, as described below.\r
+ \r
+\r
+ There is a simple variable-substitution facility for script files.\r
+ Variables can be set by the command-line -D> option,\r
+ explained above, or by the meta commands explained below.\r
+ In addition to any variables preset by -D> command-line options,\r
+ the variable scale> is preset to the current scale factor.\r
+ Once set, a variable's\r
+ value can be inserted into a SQL command by writing\r
+ :>variablename>. When running more than\r
+ one client session, each session has its own set of variables.\r
+ \r
+\r
+ Script file meta commands begin with a backslash (\>).\r
+ Arguments to a meta command are separated by white space.\r
+ These meta commands are supported:\r
+ \r
+\r
+ \r
+ \r
+ \r
+ \set varname> operand1> [ operator> operand2> ]\r
+ \r
+\r
+ \r
+ Sets variable varname> to a calculated integer value.\r
+ Each operand> is either an integer constant or a\r
+ :>variablename> reference to a variable\r
+ having an integer value. The operator> can be\r
+ +>, ->, *>, or />.\r
+ \r
+\r
+ Example:\r
+\set ntellers 10 * :scale\r
+ \r
+ \r
+ \r
+ \r
+\r
+ \r
+ \r
+ \setrandom varname> min> max>\r
+ \r
+\r
+ \r
+ Sets variable varname> to a random integer value\r
+ between the limits min> and max> inclusive.\r
+ Each limit can be either an integer constant or a\r
+ :>variablename> reference to a variable\r
+ having an integer value.\r
+ \r
+\r
+ Example:\r
+\setrandom aid 1 :naccounts\r
+ \r
+ \r
+ \r
+ \r
+\r
+ \r
+ \r
+ \sleep number> [ us | ms | s ]\r
+ \r
+\r
+ \r
+ Causes script execution to sleep for the specified duration in\r
+ microseconds (us>), milliseconds (ms>) or seconds\r
+ (s>). If the unit is omitted then seconds are the default.\r
+ number> can be either an integer constant or a\r
+ :>variablename> reference to a variable\r
+ having an integer value.\r
+ \r
+\r
+ Example:\r
+\sleep 10 ms\r
+ \r
+ \r
+ \r
+ \r
+\r
+ \r
+ \r
+ \setshell varname> command> [ argument> ... ]\r
+ \r
+\r
+ \r
+ Sets variable varname> to the result of the shell command\r
+ command>. The command must return an integer value\r
+ through its standard output.\r
+ \r
+\r
+ argument> can be either a text constant or a\r
+ :>variablename> reference to a variable of\r
+ any types. If you want to use argument> starting with\r
+ colons, you need to add an additional colon at the beginning of\r
+ argument>.\r
+ \r
+\r
+ Example:\r
+\setshell variable_to_be_assigned command literal_argument :variable ::literal_starting_with_colon\r
+ \r
+ \r
+ \r
+ \r
+\r
+ \r
+ \r
+ \shell command> [ argument> ... ]\r
+ \r
+\r
+ \r
+ Same as \setshell, but the result is ignored.\r
+ \r
+\r
+ Example:\r
+\shell command literal_argument :variable ::literal_starting_with_colon\r
+ \r
+ \r
+ \r
+ \r
+ \r
+\r
+ As an example, the full definition of the built-in TPC-B-like\r
+ transaction is:\r
+\r
+\set nbranches :scale\r
+\set ntellers 10 * :scale\r
+\set naccounts 100000 * :scale\r
+\setrandom aid 1 :naccounts\r
+\setrandom bid 1 :nbranches\r
+\setrandom tid 1 :ntellers\r
+\setrandom delta -5000 5000\r
+BEGIN;\r
+UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\r
+SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\r
+UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\r
+UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\r
+INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\r
+END;\r
+ \r
+\r
+ This script allows each iteration of the transaction to reference\r
+ different, randomly-chosen rows. (This example also shows why it's\r
+ important for each client session to have its own variables —\r
+ otherwise they'd not be independently touching different rows.)\r
+ \r
+\r
+ \r
+\r
+ \r
+
Per-transaction logging\r
+\r
+ With the
-l> option, pgbench> writes the time\r
+ taken by each transaction to a logfile. The logfile will be named\r
+ pgbench_log.nnn>, where\r
+ nnn> is the PID of the pgbench process.\r
+ If the -j> option is 2 or higher, creating multiple worker\r
+ threads, each will have its own log file. The first worker will use the\r
+ the same name for its log file as in the standard single worker case. \r
+ The additional log files for the other workers will be named\r
+ pgbench_log.nnn>.mmm>,\r
+ where mmm> is a sequential number for each worker starting\r
+ with 1.\r
+ \r
+\r
+ The format of the log is:\r
+\r
+ client_id> transaction_no> time> file_no> time_epoch> time_us>\r
+ \r
+\r
+ where time> is the elapsed transaction time in microseconds,\r
+ file_no> identifies which script file was used\r
+ (useful when multiple scripts were specified with -f>),\r
+ and time_epoch>/time_us> are a\r
+ UNIX epoch format timestamp and an offset\r
+ in microseconds (suitable for creating a ISO 8601\r
+ timestamp with fractional seconds) showing when\r
+ the transaction completed.\r
+ \r
+\r
+ Here are example outputs:\r
+ 0 199 2241 0 1175850568 995598\r
+ 0 200 2465 0 1175850568 998079\r
+ 0 201 2513 0 1175850569 608\r
+ 0 202 2038 0 1175850569 2663\r
+ \r
+ \r
+ \r
+\r
+ \r
+
Good Practices\r
+\r
+ It is very easy to use
pgbench> to produce completely\r
+ meaningless numbers. Here are some guidelines to help you get useful\r
+ results.\r
+ \r
+\r
+ In the first place, never> believe any test that runs\r
+ for only a few seconds. Use the -t> or -T> option\r
+ to make the run last at least a few minutes, so as to average out noise.\r
+ In some cases you could need hours to get numbers that are reproducible.\r
+ It's a good idea to try the test run a few times, to find out if your\r
+ numbers are reproducible or not.\r
+ \r
+\r
+ For the default TPC-B-like test scenario, the initialization scale factor\r
+ (-s>) should be at least as large as the largest number of\r
+ clients you intend to test (-c>); else you'll mostly be\r
+ measuring update contention. There are only -s> rows in\r
+ the pgbench_branches> table, and every transaction wants to\r
+ update one of them, so -c> values in excess of -s>\r
+ will undoubtedly result in lots of transactions blocked waiting for\r
+ other transactions.\r
+ \r
+\r
+ The default test scenario is also quite sensitive to how long it's been\r
+ since the tables were initialized: accumulation of dead rows and dead space\r
+ in the tables changes the results. To understand the results you must keep\r
+ track of the total number of updates and when vacuuming happens. If\r
+ autovacuum is enabled it can result in unpredictable changes in measured\r
+ performance.\r
+ \r
+\r
+ A limitation of
pgbench> is that it can itself become\r
+ the bottleneck when trying to test a large number of client sessions.\r
+ This can be alleviated by running
pgbench> on a different\r
+ machine from the database server, although low network latency will be\r
+ essential. It might even be useful to run several
pgbench>\r
+ instances concurrently, on several client machines, against the same\r
+ database server.\r
+ \r
+ \r
+\r
+\r