Use COPY FREEZE in pgbench for faster benchmark table population.

While populating the pgbench_accounts table, plain COPY was
unconditionally used. By changing it to COPY FREEZE, the time for
VACUUM is significantly reduced, thus the total time of "pgbench -i"
is also reduced. This only happens if pgbench runs against PostgreSQL
14 or later because COPY FREEZE in previous versions of PostgreSQL does
not bring the benefit. Also if partitioning is used, COPY FREEZE
cannot be used. In this case plain COPY will be used too.

Author: Tatsuo Ishii
Discussion: https://postgr.es/m/20210308.143907.2014279678657453983.t-ishii@gmail.com
Reviewed-by: Fabien COELHO, Laurenz Albe, Peter Geoghegan, Dean Rasheed
This commit is contained in:
Tatsuo Ishii 2021-09-02 10:39:09 +09:00
parent 469150a240
commit 06ba4a63b8
2 changed files with 13 additions and 1 deletions

View File

@ -220,6 +220,9 @@ pgbench <optional> <replaceable>options</replaceable> </optional> <replaceable>d
data is generated in <command>pgbench</command> client and then
sent to the server. This uses the client/server bandwidth
extensively through a <command>COPY</command>.
<command>pgbench</command> uses the FREEZE option with 14 or later
versions of <productname>PostgreSQL</productname> to speed up
subsequent <command>VACUUM</command>, unless partitions are enabled.
Using <literal>g</literal> causes logging to print one message
every 100,000 rows while generating data for the
<structname>pgbench_accounts</structname> table.

View File

@ -4153,6 +4153,7 @@ initGenerateDataClientSide(PGconn *con)
PGresult *res;
int i;
int64 k;
char *copy_statement;
/* used to track elapsed time and estimate of the remaining time */
pg_time_usec_t start;
@ -4199,7 +4200,15 @@ initGenerateDataClientSide(PGconn *con)
/*
* accounts is big enough to be worth using COPY and tracking runtime
*/
res = PQexec(con, "copy pgbench_accounts from stdin");
/* use COPY with FREEZE on v14 and later without partioning */
if (partitions == 0 && PQserverVersion(con) >= 140000)
copy_statement = "copy pgbench_accounts from stdin with (freeze on)";
else
copy_statement = "copy pgbench_accounts from stdin";
res = PQexec(con, copy_statement);
if (PQresultStatus(res) != PGRES_COPY_IN)
{
pg_log_fatal("unexpected copy in result: %s", PQerrorMessage(con));