(2014/02/16 7:38), Fabien COELHO wrote:
I have updated the patch (v7) based on Mitsumasa latest v6:
- some code simplifications & formula changes.
- I've added explicit looping probability computations in comments
to show the (low) looping probability of the iterative search.
- I've tried to clarify the sgml documentation.
- I've removed the 5.0 default value as it was not used anymore.
- I've renamed some variables to match the naming style around.
Thank you for yor detail review and fix some code! I checked your modification
version,
it seems better than previos version and very helpful for documents.
* Mathematical soundness
I've checked again the mathematical soundness for the methods involved.
After further thoughts, I'm not that sure that there is not a bias induced
by taking the second value based on "cos" when the first based on "sin"
as failed the test. So I removed the cos computation for the gaussian
version,
and simplified the code accordingly. This mean that it may be a little
less efficient, but I'm more confident that there is no bias.
I tried to confirm which method is better. However, at the end of the day, it is
not a problem because other part of implementations have bigger overhead in
pgbench client. We like simple implementaion so I agree with your modification
version. And I tested this version, there is no overhead in creating gaussian and
exponential random number with minimum threshold that is most overhead situation.
* Conclusion
If Mitsumasa-san is okay with the changes I have made, I would suggest
to accept this patch.
Attached patch based on v7 is added output that is possibility of access record
when we use exponential option
in the end of pgbench result. It is caluculated by a definite integral method for
e^-x.
If you check it and think no problem, please mark it ready for commiter.
Ishii-san will review this patch:)
Regards,
--
Mitsumasa KONDO
NTT Open Source Software Center
*** a/contrib/pgbench/pgbench.c
--- b/contrib/pgbench/pgbench.c
***************
*** 98,103 **** static int pthread_join(pthread_t th, void **thread_return);
--- 98,106 ----
#define LOG_STEP_SECONDS 5 /* seconds between log messages */
#define DEFAULT_NXACTS 10 /* default nxacts */
+ #define MIN_GAUSSIAN_THRESHOLD 2.0 /* minimum threshold for gauss */
+ #define MIN_EXPONENTIAL_THRESHOLD 2.0 /* minimum threshold for exp */
+
int nxacts = 0; /* number of transactions per client */
int duration = 0; /* duration in seconds */
***************
*** 169,174 **** bool is_connect; /* establish connection for each transaction */
--- 172,185 ----
bool is_latencies; /* report per-command latencies */
int main_pid; /* main process id used in log filename */
+ /* gaussian distribution tests: */
+ double stdev_threshold; /* standard deviation threshold */
+ bool use_gaussian = false;
+
+ /* exponential distribution tests: */
+ double exp_threshold; /* threshold for exponential */
+ bool use_exponential = false;
+
char *pghost = "";
char *pgport = "";
char *login = NULL;
***************
*** 330,335 **** static char *select_only = {
--- 341,428 ----
"SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
};
+ /* --exponential case */
+ static char *exponential_tpc_b = {
+ "\\set nbranches " CppAsString2(nbranches) " * :scale\n"
+ "\\set ntellers " CppAsString2(ntellers) " * :scale\n"
+ "\\set naccounts " CppAsString2(naccounts) " * :scale\n"
+ "\\setexponential aid 1 :naccounts :exp_threshold\n"
+ "\\setrandom bid 1 :nbranches\n"
+ "\\setrandom tid 1 :ntellers\n"
+ "\\setrandom delta -5000 5000\n"
+ "BEGIN;\n"
+ "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
+ "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
+ "UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\n"
+ "UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\n"
+ "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
+ "END;\n"
+ };
+
+ /* --exponential with -N case */
+ static char *exponential_simple_update = {
+ "\\set nbranches " CppAsString2(nbranches) " * :scale\n"
+ "\\set ntellers " CppAsString2(ntellers) " * :scale\n"
+ "\\set naccounts " CppAsString2(naccounts) " * :scale\n"
+ "\\setexponential aid 1 :naccounts :exp_threshold\n"
+ "\\setrandom bid 1 :nbranches\n"
+ "\\setrandom tid 1 :ntellers\n"
+ "\\setrandom delta -5000 5000\n"
+ "BEGIN;\n"
+ "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
+ "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
+ "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
+ "END;\n"
+ };
+
+ /* --exponential with -S case */
+ static char *exponential_select_only = {
+ "\\set naccounts " CppAsString2(naccounts) " * :scale\n"
+ "\\setexponential aid 1 :naccounts :exp_threshold\n"
+ "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
+ };
+
+ /* --gaussian case */
+ static char *gaussian_tpc_b = {
+ "\\set nbranches " CppAsString2(nbranches) " * :scale\n"
+ "\\set ntellers " CppAsString2(ntellers) " * :scale\n"
+ "\\set naccounts " CppAsString2(naccounts) " * :scale\n"
+ "\\setgaussian aid 1 :naccounts :stdev_threshold\n"
+ "\\setrandom bid 1 :nbranches\n"
+ "\\setrandom tid 1 :ntellers\n"
+ "\\setrandom delta -5000 5000\n"
+ "BEGIN;\n"
+ "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
+ "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
+ "UPDATE pgbench_tellers SET tbalance = tbalance + :delta WHERE tid = :tid;\n"
+ "UPDATE pgbench_branches SET bbalance = bbalance + :delta WHERE bid = :bid;\n"
+ "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
+ "END;\n"
+ };
+
+ /* --gaussian with -N case */
+ static char *gaussian_simple_update = {
+ "\\set nbranches " CppAsString2(nbranches) " * :scale\n"
+ "\\set ntellers " CppAsString2(ntellers) " * :scale\n"
+ "\\set naccounts " CppAsString2(naccounts) " * :scale\n"
+ "\\setgaussian aid 1 :naccounts :stdev_threshold\n"
+ "\\setrandom bid 1 :nbranches\n"
+ "\\setrandom tid 1 :ntellers\n"
+ "\\setrandom delta -5000 5000\n"
+ "BEGIN;\n"
+ "UPDATE pgbench_accounts SET abalance = abalance + :delta WHERE aid = :aid;\n"
+ "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
+ "INSERT INTO pgbench_history (tid, bid, aid, delta, mtime) VALUES (:tid, :bid, :aid, :delta, CURRENT_TIMESTAMP);\n"
+ "END;\n"
+ };
+
+ /* --gaussian with -S case */
+ static char *gaussian_select_only = {
+ "\\set naccounts " CppAsString2(naccounts) " * :scale\n"
+ "\\setgaussian aid 1 :naccounts :stdev_threshold\n"
+ "SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
+ };
+
/* Function prototypes */
static void setalarm(int seconds);
static void *threadRun(void *arg);
***************
*** 373,378 **** usage(void)
--- 466,473 ----
" -v, --vacuum-all vacuum all four standard tables before tests\n"
" --aggregate-interval=NUM aggregate data over NUM seconds\n"
" --sampling-rate=NUM fraction of transactions to log (e.g. 0.01 for 1%%)\n"
+ " --exponential=NUM exponential distribution with NUM threshold parameter\n "
+ " --gaussian=NUM gaussian distribution with NUM standard deviation threshold\n"
"\nCommon options:\n"
" -d, --debug print debugging output\n"
" -h, --host=HOSTNAME database server host or socket directory\n"
***************
*** 469,474 **** getrand(TState *thread, int64 min, int64 max)
--- 564,642 ----
return min + (int64) ((max - min + 1) * pg_erand48(thread->random_state));
}
+ /* random number generator: exponential distribution from min to max inclusive */
+ static int64
+ getExponentialrand(TState *thread, int64 min, int64 max, double exp_threshold)
+ {
+ double rand;
+
+ /*
+ * Get user specified random number in this loop. This loop is executed until
+ * the number in the expected range. As the minimum threshold is 2.0, the
+ * probability of a retry is at worst 13.5% as - ln(0.135) ~ 2.0 ;
+ * For a 5.0 threshold, it is about e^{-5} ~ 0.7%.
+ */
+ do
+ {
+ /* as pg_erand48 is in [0, 1), uniform is in (0, 1] */
+ double uniform = 1.0 - pg_erand48(thread->random_state);
+ /* rand is in [0 LARGE) */
+ rand = - log(uniform);
+ } while (rand >= exp_threshold);
+
+ /* rand in [0, exp_threshold), normalized to [0,1) */
+ rand /= exp_threshold;
+
+ /* return int64 random number within between min and max */
+ return min + (int64)((max - min + 1) * rand);
+ }
+
+ /* random number generator: gaussian distribution from min to max inclusive */
+ static int64
+ getGaussianrand(TState *thread, int64 min, int64 max, double stdev_threshold)
+ {
+ double stdev;
+ double rand;
+
+ /*
+ * Get user specified random number from this loop, with
+ * -stdev_threshold < stdev <= stdev_threshold
+ *
+ * This loop is executed until the number is in the expected range.
+ *
+ * As the minimum threshold is 2.0, the probability of looping is low:
+ * sqrt(-2 ln(r)) <= 2 => r >= e^{-2} ~ 0.135, then when taking the average
+ * sinus multiplier as 2/pi, we have a 8.6% looping probability in the
+ * worst case. For a 5.0 threshold value, the looping proability
+ * is about e^{-5} * 2 / pi ~ 0.43%.
+ */
+ do
+ {
+ /*
+ * pg_erand48 generates [0,1), but for the basic version of the
+ * Box-Muller transform the two uniformly distributed random numbers
+ * are expected in (0, 1] (see http://en.wikipedia.org/wiki/Box_muller)
+ */
+ double rand1 = 1.0 - pg_erand48(thread->random_state);
+ double rand2 = 1.0 - pg_erand48(thread->random_state);
+
+ /* Box-Muller basic form transform */
+ double var_sqrt = sqrt(-2.0 * log(rand1));
+ stdev = var_sqrt * sin(2.0 * M_PI * rand2);
+
+ /* we may try with cos, but there may be a bias induced if the previous
+ * value fails the test? To be on the safe side, let us try over.
+ */
+ }
+ while (stdev < -stdev_threshold || stdev >= stdev_threshold);
+
+ /* stdev is in [-threshold, threshold), normalization to [0,1) */
+ rand = (stdev + stdev_threshold) / (stdev_threshold * 2.0);
+
+ /* return int64 random number within between min and max */
+ return min + (int64)((max - min + 1) * rand);
+ }
+
/* call PQexec() and exit() on failure */
static void
executeStatement(PGconn *con, const char *sql)
***************
*** 1307,1317 **** top:
fprintf(stderr, "\n");
}
! if (pg_strcasecmp(argv[0], "setrandom") == 0)
{
char *var;
int64 min,
max;
char res[64];
if (*argv[2] == ':')
--- 1475,1488 ----
fprintf(stderr, "\n");
}
! if ((pg_strcasecmp(argv[0], "setrandom") == 0) ||
! (pg_strcasecmp(argv[0], "setgaussian") == 0) ||
! (pg_strcasecmp(argv[0], "setexponential") == 0))
{
char *var;
int64 min,
max;
+ double threshold = 0;
char res[64];
if (*argv[2] == ':')
***************
*** 1357,1367 **** top:
}
/*
! * getrand() needs to be able to subtract max from min and add one
! * to the result without overflowing. Since we know max > min, we
! * can detect overflow just by checking for a negative result. But
! * we must check both that the subtraction doesn't overflow, and
! * that adding one to the result doesn't overflow either.
*/
if (max - min < 0 || (max - min) + 1 < 0)
{
--- 1528,1538 ----
}
/*
! * Generate random number functions need to be able to subtract
! * max from min and add one to the result without overflowing.
! * Since we know max > min, we can detect overflow just by checking
! * for a negative result. But we must check both that the subtraction
! * doesn't overflow, and that adding one to the result doesn't overflow either.
*/
if (max - min < 0 || (max - min) + 1 < 0)
{
***************
*** 1370,1379 **** top:
return true;
}
#ifdef DEBUG
! printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n", min, max, getrand(thread, min, max));
#endif
! snprintf(res, sizeof(res), INT64_FORMAT, getrand(thread, min, max));
if (!putVariable(st, argv[0], argv[1], res))
{
--- 1541,1595 ----
return true;
}
+ if (pg_strcasecmp(argv[0], "setrandom") == 0)
+ {
+ #ifdef DEBUG
+ printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n", min, max, getrand(thread, min, max));
+ #endif
+ snprintf(res, sizeof(res), INT64_FORMAT, getrand(thread, min, max));
+ }
+ else if ((pg_strcasecmp(argv[0], "setgaussian") == 0) || (pg_strcasecmp(argv[0], "setexponential") == 0))
+ {
+ if(*argv[4] == ':')
+ {
+ if((var = getVariable(st, argv[4] + 1)) == NULL)
+ {
+ fprintf(stderr, "%s: invalid threshold number %s\n", argv[0], argv[4]);
+ st->ecnt++;
+ return true;
+ }
+ threshold = strtod(var, NULL);
+ }
+ else
+ threshold = strtod(argv[4], NULL);
+
+ if (pg_strcasecmp(argv[0], "setgaussian") == 0)
+ {
+ if (threshold < MIN_GAUSSIAN_THRESHOLD)
+ {
+ fprintf(stderr, "%s: gaussian threshold must be more than 2\n,", argv[4]);
+ st->ecnt++;
+ return true;
+ }
+ #ifdef DEBUG
+ printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n", min, max, getGaussianrand(thread, min, max, threshold));
+ #endif
+ snprintf(res, sizeof(res), INT64_FORMAT, getGaussianrand(thread, min, max, threshold));
+ }
+ else if (pg_strcasecmp(argv[0], "setexponential") == 0)
+ {
+ if (threshold < MIN_EXPONENTIAL_THRESHOLD)
+ {
+ fprintf(stderr, "%s: exponential threshold must be more than 2\n,", argv[4]);
+ st->ecnt++;
+ return true;
+ }
#ifdef DEBUG
! printf("min: " INT64_FORMAT " max: " INT64_FORMAT " random: " INT64_FORMAT "\n", min, max, getExponentialrand(thread, min, max, threshold));
#endif
! snprintf(res, sizeof(res), INT64_FORMAT, getExponentialrand(thread, min, max, threshold));
! }
! }
if (!putVariable(st, argv[0], argv[1], res))
{
***************
*** 1907,1912 **** process_commands(char *buf)
--- 2123,2141 ----
fprintf(stderr, "%s: extra argument \"%s\" ignored\n",
my_commands->argv[0], my_commands->argv[j]);
}
+ else if ((pg_strcasecmp(my_commands->argv[0], "setgaussian") == 0) ||
+ (pg_strcasecmp(my_commands->argv[0], "setexponential") == 0))
+ {
+ if (my_commands->argc < 5)
+ {
+ fprintf(stderr, "%s: missing argument\n", my_commands->argv[0]);
+ exit(1);
+ }
+
+ for (j = 5; j < my_commands->argc; j++)
+ fprintf(stderr, "%s: extra argument \"%s\" ignored\n",
+ my_commands->argv[0], my_commands->argv[j]);
+ }
else if (pg_strcasecmp(my_commands->argv[0], "set") == 0)
{
if (my_commands->argc < 3)
***************
*** 2180,2195 **** printResults(int ttype, int normal_xacts, int nclients,
(INSTR_TIME_GET_DOUBLE(conn_total_time) / nthreads));
if (ttype == 0)
! s = "TPC-B (sort of)";
else if (ttype == 2)
! s = "Update only pgbench_accounts";
else if (ttype == 1)
! s = "SELECT only";
else
s = "Custom query";
printf("transaction type: %s\n", s);
printf("scaling factor: %d\n", scale);
printf("query mode: %s\n", QUERYMODE[querymode]);
printf("number of clients: %d\n", nclients);
printf("number of threads: %d\n", nthreads);
--- 2409,2465 ----
(INSTR_TIME_GET_DOUBLE(conn_total_time) / nthreads));
if (ttype == 0)
! {
! if (use_gaussian)
! s = "Gaussian distribution TPC-B (sort of)";
! else if (use_exponential)
! s = "Exponential distribution TPC-B (sort of)";
! else
! s = "TPC-B (sort of)";
! }
else if (ttype == 2)
! {
! if (use_gaussian)
! s = "Gaussian distribution update only pgbench_accounts";
! else if (use_exponential)
! s = "Exponential distribution update only pgbench_accounts";
! else
! s = "Update only pgbench_accounts";
! }
else if (ttype == 1)
! {
! if (use_gaussian)
! s = "Gaussian distribution SELECT only";
! else if (use_exponential)
! s = "Exponential distribution SELECT only";
! else
! s = "SELECT only";
! }
else
s = "Custom query";
printf("transaction type: %s\n", s);
printf("scaling factor: %d\n", scale);
+
+ /* output in gaussian distribution benchmark */
+ if (use_gaussian)
+ {
+ printf("standard deviation threshold: %.5f\n", stdev_threshold);
+ printf("access probability of top 20%%, 10%% and 5%% records: %.5f %.5f %.5f\n",
+ (double) ((erf (stdev_threshold * 0.2 / sqrt(2.0))) / (erf (stdev_threshold / sqrt(2.0)))),
+ (double) ((erf (stdev_threshold * 0.1 / sqrt(2.0))) / (erf (stdev_threshold / sqrt(2.0)))),
+ (double) ((erf (stdev_threshold * 0.05 / sqrt(2.0))) / (erf (stdev_threshold / sqrt(2.0)))));
+ }
+ /* output in exponential distribution benchmark */
+ else if (use_exponential)
+ {
+ printf("exponential threshold: %.5f\n", exp_threshold);
+ printf("access probability of top 20%%, 10%% and 5%% records: %.5f %.5f %.5f\n",
+ (double) (-exp(-exp_threshold * 0.2) + 1),
+ (double) (-exp(-exp_threshold * 0.1) + 1),
+ (double) (-exp(-exp_threshold * 0.05) + 1));
+ }
+
printf("query mode: %s\n", QUERYMODE[querymode]);
printf("number of clients: %d\n", nclients);
printf("number of threads: %d\n", nthreads);
***************
*** 2319,2324 **** main(int argc, char **argv)
--- 2589,2596 ----
{"unlogged-tables", no_argument, &unlogged_tables, 1},
{"sampling-rate", required_argument, NULL, 4},
{"aggregate-interval", required_argument, NULL, 5},
+ {"gaussian", required_argument, NULL, 6},
+ {"exponential", required_argument, NULL, 7},
{"rate", required_argument, NULL, 'R'},
{NULL, 0, NULL, 0}
};
***************
*** 2598,2605 **** main(int argc, char **argv)
}
#endif
break;
default:
! fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1);
break;
}
--- 2870,2897 ----
}
#endif
break;
+ case 6:
+ use_gaussian = true;
+ stdev_threshold = atof(optarg);
+ if(stdev_threshold < MIN_GAUSSIAN_THRESHOLD)
+ {
+ fprintf(stderr, "--gaussian=NUM must be more than %f: %f\n",
+ MIN_GAUSSIAN_THRESHOLD, stdev_threshold);
+ exit(1);
+ }
+ break;
+ case 7:
+ use_exponential = true;
+ exp_threshold = atof(optarg);
+ if(exp_threshold < MIN_EXPONENTIAL_THRESHOLD)
+ {
+ fprintf(stderr, "--exponential=NUM must be more than %f: %f\n",
+ MIN_EXPONENTIAL_THRESHOLD, exp_threshold);
+ exit(1);
+ }
+ break;
default:
! fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
exit(1);
break;
}
***************
*** 2795,2800 **** main(int argc, char **argv)
--- 3087,3114 ----
}
}
+ /* set :stdev_threshold variable */
+ if(getVariable(&state[0], "stdev_threshold") == NULL)
+ {
+ snprintf(val, sizeof(val), "%lf", stdev_threshold);
+ for (i = 0; i < nclients; i++)
+ {
+ if (!putVariable(&state[i], "startup", "stdev_threshold", val))
+ exit(1);
+ }
+ }
+
+ /* set :exp_threshold variable */
+ if(getVariable(&state[0], "exp_threshold") == NULL)
+ {
+ snprintf(val, sizeof(val), "%lf", exp_threshold);
+ for (i = 0; i < nclients; i++)
+ {
+ if (!putVariable(&state[i], "startup", "exp_threshold", val))
+ exit(1);
+ }
+ }
+
if (!is_no_vacuum)
{
fprintf(stderr, "starting vacuum...");
***************
*** 2820,2836 **** main(int argc, char **argv)
switch (ttype)
{
case 0:
! sql_files[0] = process_builtin(tpc_b);
num_files = 1;
break;
case 1:
! sql_files[0] = process_builtin(select_only);
num_files = 1;
break;
case 2:
! sql_files[0] = process_builtin(simple_update);
num_files = 1;
break;
--- 3134,3165 ----
switch (ttype)
{
case 0:
! if (use_gaussian)
! sql_files[0] = process_builtin(gaussian_tpc_b);
! else if (use_exponential)
! sql_files[0] = process_builtin(exponential_tpc_b);
! else
! sql_files[0] = process_builtin(tpc_b);
num_files = 1;
break;
case 1:
! if (use_gaussian)
! sql_files[0] = process_builtin(gaussian_select_only);
! else if (use_exponential)
! sql_files[0] = process_builtin(exponential_select_only);
! else
! sql_files[0] = process_builtin(select_only);
num_files = 1;
break;
case 2:
! if (use_gaussian)
! sql_files[0] = process_builtin(gaussian_simple_update);
! else if (use_exponential)
! sql_files[0] = process_builtin(exponential_simple_update);
! else
! sql_files[0] = process_builtin(simple_update);
num_files = 1;
break;
*** a/doc/src/sgml/pgbench.sgml
--- b/doc/src/sgml/pgbench.sgml
***************
*** 307,312 **** pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
--- 307,328 ----
</varlistentry>
<varlistentry>
+ <term><option>--exponential</option><replaceable>deviation threshold</></term>
+ <listitem>
+ <para>
+ Deviation threshold for the exponential distribution pgbench test.
+ This threshold controls the distribution of accesses on the
+ <structname>pgbench_accounts</> table.
+ The larger the deviation threshold, the more records at the beginning
+ are accessed. The smaller the deviation threshold, the smoother the access
+ pattern distribution. The deviation threshold must be more than 2 for
+ internal performance. When set, this option applies to all test variants
+ (<option>-N</> for skipping updates, or <option>-S</> for selects).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-f</option> <replaceable>filename</></term>
<term><option>--file=</option><replaceable>filename</></term>
<listitem>
***************
*** 320,325 **** pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
--- 336,357 ----
</varlistentry>
<varlistentry>
+ <term><option>--gaussian</option><replaceable>standard deviation threshold</></term>
+ <listitem>
+ <para>
+ Deviation threshold for the Gaussian distribution pgbench test.
+ This threshold controls the distribution of accesses on the
+ <structname>pgbench_accounts</> table.
+ The larger the deviation threshold, the more records in the middle of the table
+ are accessed. The smaller the deviation threshold, the smoother the access
+ pattern distribution. The deviation threshold must be more than 2 for
+ internal performance. When set, this option applies to all test variants
+ (<option>-N</> for skipping updates, or <option>-S</> for selects).
+ </para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
<term><option>-j</option> <replaceable>threads</></term>
<term><option>--jobs=</option><replaceable>threads</></term>
<listitem>
***************
*** 770,775 **** pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
--- 802,860 ----
<varlistentry>
<term>
+ <literal>\setgaussian <replaceable>varname</> <replaceable>min</> <replaceable>max</> <replaceable>
+ standard deviation threshold</literal>
+ </term>
+
+ <listitem>
+ <para>
+ Set variable <replaceable>varname</> to a gaussian random integer value
+ between <replaceable>min</> and <replaceable>max</> bounds inclusive.
+ Each bound can be either an integer constant or a
+ <literal>:</><replaceable>variablename</> reference to a variable
+ having an integer value. The standard deviation threshold controls
+ the distribution pattern. The larger the threshold, the more frequent
+ values close to the middle of the interval are drawn. The threshold is
+ the deviation for the <replaceable>min</> and <replaceable>max</> bounds.
+ The minimum threshold is 2.0, for performance.
+ </para>
+
+ <para>
+ Example:
+ <programlisting>
+ \setgaussian aid 1 :naccounts 5
+ </programlisting></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
+ <literal>\setexponential <replaceable>varname</> <replaceable>min</> <replaceable>max</> <replaceable>
+ deviation threshold</literal>
+ </term>
+
+ <listitem>
+ <para>
+ Set variable <replaceable>varname</> to an exponential random integer value
+ between <replaceable>min</> and <replaceable>max</> bounds inclusive.
+ Each bound can be either an integer constant or a
+ <literal>:</><replaceable>variablename</> reference to a variable
+ having an integer value. The deviation threshold controls the distribution
+ pattern: the larger the deviation threshold, the more frequent values
+ close to <replaceable>min</> are drawn.
+ The minimum threshold is 2.0, for performance.
+ </para>
+
+ <para>
+ Example:
+ <programlisting>
+ \setexponential aid 1 :naccounts 5
+ </programlisting></para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>
<literal>\sleep <replaceable>number</> [ us | ms | s ]</literal>
</term>
--
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers