diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml index c575f19..790f075 100644 --- a/doc/src/sgml/ref/pgbench.sgml +++ b/doc/src/sgml/ref/pgbench.sgml @@ -882,6 +882,11 @@ pgbench options d client_id unique number identifying the client session (starts from zero) + + + random_seed + random seed shared for all sessions + @@ -1444,6 +1449,22 @@ f(x) = PHI(2.0 * parameter * (x - mu) / (max - min + 1)) / + Hash functions accepts an input value and optional seed parameter. In case seed isn't provided :random_seed value is used. Hash functions can be used, for example, to modify the distribution of random_zipfian or random_exponential functions in order to obtain scattered distribution. Thus the following listing simulates some possible real world workload typical for social media and blogging platforms where few accounts generates excessive load: + + +\set r random_zipfian(0, 100000, 0.99) +\set k abs(hash(:r)) % 1000 + + + In some cases several distinct distributions are needed which don't correlate with each other and this is when implicit seed parameter comes in handy: + + +\set k1 abs(hash(:r), :random_seed + 123) % 1000 +\set k2 abs(hash(:r), :random_seed + 321) % 1000 + + + + As an example, the full definition of the built-in TPC-B-like transaction is: diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index 6e0f340..b6ed829 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -192,8 +192,6 @@ char *dbName; char *logfile_prefix = NULL; const char *progname; -int hash_seed; - #define WSEP '@' /* weight separator */ volatile bool timer_exceeded = false; /* flag from signal handler */ @@ -449,8 +447,6 @@ static int num_scripts; /* number of scripts in sql_script[] */ static int num_commands = 0; /* total number of Command structs */ static int64 total_weight = 0; -static int hash_seed; /* default seed used in hash functions */ - static int debug = 0; /* debug flag */ /* Builtin test scripts */ @@ -2286,7 +2282,18 @@ evalStandardFunc( return false; } else - seed = hash_seed; + { + Variable *var; + + /* read seed from variable */ + var = lookupVariable(st, "random_seed"); + Assert(var != NULL); + if (var->value.type == PGBT_NO_VALUE) + if (!makeVariableValue(var)) + return false; + if (!coerceToInt(&var->value, &seed)) + return false; + } result = (func == PGBENCH_HASH_FNV1A) ? getHashFnv1a(val, seed) : getHashMurmur2(val, seed); @@ -5004,6 +5011,10 @@ main(int argc, char **argv) */ main_pid = (int) getpid(); + /* set random seed */ + INSTR_TIME_SET_CURRENT(start_time); + srandom((unsigned int) INSTR_TIME_GET_MICROSEC(start_time)); + if (nclients > 1) { state = (CState *) pg_realloc(state, sizeof(CState) * nclients); @@ -5118,6 +5129,16 @@ main(int argc, char **argv) } } + /* set default seed for hash functions */ + if (lookupVariable(&state[0], "random_seed") == NULL) + { + int64 seed = random(); + + for (i = 0; i < nclients; i++) + if (!putVariableInt(&state[i], "startup", "random_seed", seed)) + exit(1); + } + if (!is_no_vacuum) { fprintf(stderr, "starting vacuum..."); @@ -5135,13 +5156,6 @@ main(int argc, char **argv) } PQfinish(con); - /* set random seed */ - INSTR_TIME_SET_CURRENT(start_time); - srandom((unsigned int) INSTR_TIME_GET_MICROSEC(start_time)); - - /* set default seed for hash functions */ - hash_seed = random(); - /* set up thread data structures */ threads = (TState *) pg_malloc(sizeof(TState) * nthreads); nclients_dealt = 0; diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h index 6070908..6983865 100644 --- a/src/bin/pgbench/pgbench.h +++ b/src/bin/pgbench/pgbench.h @@ -138,7 +138,6 @@ struct PgBenchExprList }; extern PgBenchExpr *expr_parse_result; -extern int hash_seed; extern int expr_yyparse(yyscan_t yyscanner); extern int expr_yylex(union YYSTYPE *lvalp, yyscan_t yyscanner);