Gaussian Pgbench v8 patch by Mitsumasa KONDO review & patch v9.

* The purpose of the patch is to allow a pgbench script to draw from normally
  distributed or exponentially distributed integer values instead of uniformly
  distributed.

  This is a valuable contribution to enable pgbench to generate more realistic
  loads, which is seldom uniform in practice.

* Very minor change

  I have updated the patch (v9) based on Mitsumasa latest v8:
  - remove one spurious space in the help message.

* Compilation

  The patch applies cleanly and compiles against current head.

* Check

  I have checked that the aid values are skewed depending on the
  parameters by looking at the "aid" distribution in the "pgbench_history"
  table after a run.

* Mathematical soundness

  I've checked the mathematical soundness of the methods involved.

  I'm fine with casting doubles to integers for having the expected
  distribution on integers.

  Although there is a retry loop for finding a suitable, the looping
  probability is low thanks to the minimum threshold parameter required.

* Conclusion

  I suggest to apply this patch which provide a useful and more realistic
  testing capability to pgbench.

--
Fabien.
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c
index a836acf..35edd27 100644
--- a/contrib/pgbench/pgbench.c
+++ b/contrib/pgbench/pgbench.c
@@ -98,6 +98,9 @@ static int	pthread_join(pthread_t th, void **thread_return);
 #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,6 +172,14 @@ bool		is_connect;			/* establish connection for each transaction */
 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,6 +341,88 @@ static char *select_only = {
 	"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,6 +466,8 @@ usage(void)
 		   "  -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,6 +564,79 @@ getrand(TState *thread, int64 min, int64 max)
 	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,11 +1475,14 @@ top:
 			fprintf(stderr, "\n");
 		}
 
-		if (pg_strcasecmp(argv[0], "setrandom") == 0)
+		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,11 +1528,11 @@ 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.
+			 * 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,10 +1541,55 @@ top:
 				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, getrand(thread, min, max));
+					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, getrand(thread, min, max));
+					snprintf(res, sizeof(res), INT64_FORMAT, getExponentialrand(thread, min, max, threshold));
+				}
+			}
 
 			if (!putVariable(st, argv[0], argv[1], res))
 			{
@@ -1907,6 +2123,19 @@ process_commands(char *buf)
 				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,16 +2409,57 @@ printResults(int ttype, int normal_xacts, int nclients,
 						(INSTR_TIME_GET_DOUBLE(conn_total_time) / nthreads));
 
 	if (ttype == 0)
-		s = "TPC-B (sort of)";
+	{
+		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)
-		s = "Update only pgbench_accounts";
+	{
+		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)
-		s = "SELECT only";
+	{
+		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,6 +2589,8 @@ main(int argc, char **argv)
 		{"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,8 +2870,28 @@ main(int argc, char **argv)
 				}
 #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);
+				fprintf(stderr, _("Try \"%s --help\" for more information.\n"),	progname);
 				exit(1);
 				break;
 		}
@@ -2795,6 +3087,28 @@ main(int argc, char **argv)
 		}
 	}
 
+	/* 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,17 +3134,32 @@ main(int argc, char **argv)
 	switch (ttype)
 	{
 		case 0:
-			sql_files[0] = process_builtin(tpc_b);
+			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:
-			sql_files[0] = process_builtin(select_only);
+			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:
-			sql_files[0] = process_builtin(simple_update);
+			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;
 
diff --git a/doc/src/sgml/pgbench.sgml b/doc/src/sgml/pgbench.sgml
index 05ca9b7..3e4bcea 100644
--- a/doc/src/sgml/pgbench.sgml
+++ b/doc/src/sgml/pgbench.sgml
@@ -307,6 +307,22 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
      </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,6 +336,22 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
      </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,6 +802,59 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
 
    <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

Reply via email to