Re: pgbench -f and vacuum - Mailing list pgsql-hackers
From | Tatsuo Ishii |
---|---|
Subject | Re: pgbench -f and vacuum |
Date | |
Msg-id | 20141222.153636.2103937067895645047.t-ishii@sraoss.co.jp Whole thread Raw |
In response to | Re: pgbench -f and vacuum (Tomas Vondra <tv@fuzzy.cz>) |
Responses |
Re: pgbench -f and vacuum
|
List | pgsql-hackers |
> Hi, > > On 21.12.2014 15:58, Tatsuo Ishii wrote: >>> On Sun, Dec 14, 2014 at 11:43 AM, Tatsuo Ishii <ishii@postgresql.org> wrote: >>>>> If we care enough about that case to attempt the vacuum anyway >>>>> then we need to do something about the error message; either >>>>> squelch it or check for the existence of the tables before >>>>> attempting to vacuum. Since there's no way to squelch in the >>>>> server logfile, I think checking for the table is the right >>>>> answer. >>>> >>>> Fair enough. I will come up with "checking for table before >>>> vacuum" approach. >>> >>> +1 for this approach. >> >> Here is the patch I promised. > > First of all - I'm not entirely convinced the "IF EXISTS" approach is > somehow better than "-f implies -n" suggested before, but I don't have a > strong preference either. > > Regarding the patch: > > (1) I agree with Fabrizio that the 'executeStatement2' is not the best > naming as it does not show the 'if exists' intent. > > > (2) The 'executeStatement2' API is a bit awkward as the signarure > > executeStatement2(PGconn *con, const char *sql, const char *table); > > suggests that the 'sql' command is executed when 'table' exists. > But that's not the case, because what actually gets executed is > 'sql table'. Any replacement idea for "sql" and "table"? > (3) The 'is_table_exists' should be probably just 'table_exists'. > > > (4) The SQL used in is_table_exists to check table existence seems > slightly wrong, because 'to_regclass' works for other relation > kinds, not just regular tables - it will match views for example. > While a conflict like that (having an object with the right name > but not a regular table) is rather unlikely I guess, a more correct > query would be this: > > SELECT oid FROM pg_class WHERE relname = '%s' AND relkind = 'r'; This doesn't always work if schema search path is set. > (5) I'm not a libpq expert, but I don't see how the PQgetvalue() could > return anything except true/false, so the > > if (result == NULL) > { > PQclear(res); > return false; > } > > seems a bit pointless to me. But maybe it's necessary? PQgetvalue could return NULL, if the parameter is wrong. I don't want to raise segfault in any case. > (6) The is_table_exists might be further simplified along these lines: > > static bool > is_table_exists(PGconn *con, const char *table) > { > PGresult *res; > char buf[1024]; > char *result; > bool retval; > > snprintf(buf, sizeof(buf)-1, > "SELECT to_regclass('%s') IS NULL", table); > > res = PQexec(con, buf); > if (PQresultStatus(res) != PGRES_TUPLES_OK) > { > return false; > } > > result = PQgetvalue(res, 0, 0); > > retval = (*result == 't'); > > PQclear(res); > > return retval; > } > > > (7) I also find the coding in main() around line 3250 a bit clumsy. The > first reason is that it only checks existence of 'pgbench_branches' > and then vacuums three pgbench_tellers and pgbench_history in the > same block. If pgbench_branches does not exist, there will be no > message printed (but the tables will be vacuumed). So we should check the existence of all pgbench_branches, pgbench_tellers, pgbench_history and pgbench_accounts? Not sure if it's worth the trouble. > The second reason is that the msg1, msg2 variables seem unnecessary. > IMHO this is a bit better: This will behave differently from what pgbench it is now. If -f is not specified and pgbench_* does not exist, then pgbech silently skipps vacuum. Today pgbench raises error in this case. > if (!is_no_vacuum) > { > if (is_table_exists(con, "pgbench_branches")) > { > fprintf(stderr, "starting vacuum..."); > > executeStatement2(con, "vacuum", "pgbench_branches"); > executeStatement2(con, "vacuum", "pgbench_tellers"); > executeStatement2(con, "truncate", "pgbench_history"); > > fprintf(stderr, "end.\n"); > } > > if (do_vacuum_accounts) > { > if (is_table_exists(con, "pgbench_accounts")) > { > fprintf(stderr, "starting vacuum pgbench_accounts..."); > > executeStatement(con, > "vacuum analyze pgbench_accounts"); > > fprintf(stderr, "end.\n"); > } > } > } > > (8) Also, I think it's not necessary to define function prototypes for > executeStatement2 and is_table_exists. It certainly is not > consistent with the other functions defined in pgbench.c (e.g. > there's no prototype for executeStatement). Just delete the two > prototypes and move is_table_exists before executeStatement2. I think not having static function prototypes is not a good custom. See other source code in PostgreSQL. Best regards, -- Tatsuo Ishii SRA OSS, Inc. Japan English: http://www.sraoss.co.jp/index_en.php Japanese:http://www.sraoss.co.jp
pgsql-hackers by date: