Gaussian Pgbench v6 patch by Mitsumasa KONDO review & patch v7.

* 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.

* Changes

  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.

* Compilation

  The patch applies and compiles against current head. It works as expected,
  although there is few feedback from the script to show that. By looking
  at the "aid" distribution in the "pgbench_history" table after a run, I
  could check that the aid values are indeed skewed, depending on the 
parameters.

* 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.

* Conclusion

  If Mitsumasa-san is okay with the changes I have made, I would suggest
  to accept this patch.

--
Fabien.
diff --git a/contrib/pgbench/pgbench.c b/contrib/pgbench/pgbench.c
index 16b7ab5..afe4a32 100644
--- a/contrib/pgbench/pgbench.c
+++ b/contrib/pgbench/pgbench.c
@@ -106,6 +106,9 @@ extern int	optind;
 #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 */
 
@@ -177,6 +180,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;
@@ -338,6 +349,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);
@@ -381,6 +474,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"
@@ -477,6 +572,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)
@@ -1315,11 +1483,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] == ':')
@@ -1365,11 +1536,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)
 			{
@@ -1378,10 +1549,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));
+				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));
+				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))
 			{
@@ -1915,6 +2131,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)
@@ -2188,16 +2417,47 @@ 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 distributed TPC-B (sort of)";
+		else if (use_exponential)
+			s = "Exponential distributed TPC-B (sort of)";
+		else
+			s = "TPC-B (sort of)";
+	}
 	else if (ttype == 2)
-		s = "Update only pgbench_accounts";
+	{
+		if (use_gaussian)
+			s = "Gaussian distributed update only pgbench_accounts";
+		else if (use_exponential)
+			s = "Exponential distributed update only pgbench_accounts";
+		else
+			s = "Update only pgbench_accounts";
+	}
 	else if (ttype == 1)
-		s = "SELECT only";
+	{
+		if (use_gaussian)
+			s = "Gaussian distributed SELECT only";
+		else if (use_exponential)
+			s = "Exponential distributed SELECT only";
+		else
+			s = "SELECT only";
+	}
 	else
 		s = "Custom query";
 
 	printf("transaction type: %s\n", s);
 	printf("scaling factor: %d\n", scale);
+
+	/* output in only gaussian distributed 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)))));
+	}
 	printf("query mode: %s\n", QUERYMODE[querymode]);
 	printf("number of clients: %d\n", nclients);
 	printf("number of threads: %d\n", nthreads);
@@ -2327,6 +2587,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}
 	};
@@ -2606,8 +2868,29 @@ 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;
 		}
@@ -2803,6 +3086,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...");
@@ -2828,17 +3133,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