*** a/contrib/pgbench/pgbench.c
--- b/contrib/pgbench/pgbench.c
***************
*** 41,46 ****
--- 41,47 ----
  #include <math.h>
  #include <signal.h>
  #include <sys/time.h>
+ #include <assert.h>
  #ifdef HAVE_SYS_SELECT_H
  #include <sys/select.h>
  #endif
***************
*** 157,162 **** char	   *index_tablespace = NULL;
--- 158,164 ----
   * document and remember, and isn't that far away from the real threshold.
   */
  #define SCALE_32BIT_THRESHOLD 20000
+ #define MIN_GAUSSIAN_THRESHOLD 2.0
  
  bool		use_log;			/* log transaction latencies to a file */
  bool		use_quiet;			/* quiet logging onto stderr */
***************
*** 171,176 **** bool		is_connect;			/* establish connection for each transaction */
--- 173,183 ----
  bool		is_latencies;		/* report per-command latencies */
  int			main_pid;			/* main process id used in log filename */
  
+ /* gaussian/exponential distribution tests */
+ double		threshold;          /* threshold for gaussian or exponential */
+ bool        use_gaussian = false;
+ bool		use_exponential = false;
+ 
  char	   *pghost = "";
  char	   *pgport = "";
  char	   *login = NULL;
***************
*** 292,302 **** static int	num_commands = 0;	/* total number of Command structs */
  static int	debug = 0;			/* debug flag */
  
  /* default scenario */
! static char *tpc_b = {
  	"\\set nbranches " CppAsString2(nbranches) " * :scale\n"
  	"\\set ntellers " CppAsString2(ntellers) " * :scale\n"
  	"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
! 	"\\setrandom aid 1 :naccounts\n"
  	"\\setrandom bid 1 :nbranches\n"
  	"\\setrandom tid 1 :ntellers\n"
  	"\\setrandom delta -5000 5000\n"
--- 299,309 ----
  static int	debug = 0;			/* debug flag */
  
  /* default scenario */
! static char *tpc_b_fmt = {
  	"\\set nbranches " CppAsString2(nbranches) " * :scale\n"
  	"\\set ntellers " CppAsString2(ntellers) " * :scale\n"
  	"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
! 	"\\setrandom aid 1 :naccounts%s\n"
  	"\\setrandom bid 1 :nbranches\n"
  	"\\setrandom tid 1 :ntellers\n"
  	"\\setrandom delta -5000 5000\n"
***************
*** 310,320 **** static char *tpc_b = {
  };
  
  /* -N case */
! static char *simple_update = {
  	"\\set nbranches " CppAsString2(nbranches) " * :scale\n"
  	"\\set ntellers " CppAsString2(ntellers) " * :scale\n"
  	"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
! 	"\\setrandom aid 1 :naccounts\n"
  	"\\setrandom bid 1 :nbranches\n"
  	"\\setrandom tid 1 :ntellers\n"
  	"\\setrandom delta -5000 5000\n"
--- 317,327 ----
  };
  
  /* -N case */
! static char *simple_update_fmt = {
  	"\\set nbranches " CppAsString2(nbranches) " * :scale\n"
  	"\\set ntellers " CppAsString2(ntellers) " * :scale\n"
  	"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
! 	"\\setrandom aid 1 :naccounts%s\n"
  	"\\setrandom bid 1 :nbranches\n"
  	"\\setrandom tid 1 :ntellers\n"
  	"\\setrandom delta -5000 5000\n"
***************
*** 326,334 **** static char *simple_update = {
  };
  
  /* -S case */
! static char *select_only = {
  	"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
! 	"\\setrandom aid 1 :naccounts\n"
  	"SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
  };
  
--- 333,341 ----
  };
  
  /* -S case */
! static char *select_only_fmt = {
  	"\\set naccounts " CppAsString2(naccounts) " * :scale\n"
! 	"\\setrandom aid 1 :naccounts%s\n"
  	"SELECT abalance FROM pgbench_accounts WHERE aid = :aid;\n"
  };
  
***************
*** 375,380 **** usage(void)
--- 382,389 ----
  		   "  -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 threshold parameter\n"
  		   "\nCommon options:\n"
  		   "  -d, --debug              print debugging output\n"
  	  "  -h, --host=HOSTNAME      database server host or socket directory\n"
***************
*** 2178,2183 **** process_builtin(char *tb)
--- 2187,2216 ----
  	return my_commands;
  }
  
+ /*
+  * compute the probability of the truncated gaussian random generation
+  * to draw values in the i-th slot of the range.
+  */
+ static double gaussianProbability(int i, int slots, double threshold)
+ {
+ 	assert(1 <= i && i <= slots);
+ 	return (0.50 * (erf (threshold * (1.0 - 1.0 / slots * (2.0 * i - 2.0)) / sqrt(2.0)) -
+ 		erf (threshold * (1.0 - 1.0 / slots * 2.0 * i) / sqrt(2.0))) /
+ 		erf (threshold / sqrt(2.0)));
+ }
+ 
+ /*
+  * compute the probability of the truncated exponential random generation
+  * to draw values in the i-th slot of the range.
+  */
+ static double exponentialProbability(int i, int slots, double threshold)
+ {
+ 	assert(1 <= i && i <= slots);
+ 	return (exp(- threshold * (i - 1) / slots) - exp(- threshold * i / slots)) /
+ 		(1.0 - exp(- threshold));
+ }
+ 
+ 
  /* print out results */
  static void
  printResults(int ttype, int64 normal_xacts, int nclients,
***************
*** 2189,2195 **** printResults(int ttype, int64 normal_xacts, int nclients,
  	double		time_include,
  				tps_include,
  				tps_exclude;
! 	char	   *s;
  
  	time_include = INSTR_TIME_GET_DOUBLE(total_time);
  	tps_include = normal_xacts / time_include;
--- 2222,2228 ----
  	double		time_include,
  				tps_include,
  				tps_exclude;
! 	char	   *s, *d;
  
  	time_include = INSTR_TIME_GET_DOUBLE(total_time);
  	tps_include = normal_xacts / time_include;
***************
*** 2205,2212 **** printResults(int ttype, int64 normal_xacts, int nclients,
  	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);
--- 2238,2283 ----
  	else
  		s = "Custom query";
  
! 	if (use_gaussian)
! 		d = "Gaussian distribution ";
! 	else if (use_exponential)
! 		d = "Exponential distribution ";
! 	else
! 		d = ""; /* default uniform case */
! 
! 	printf("transaction type: %s%s\n", d, s);
  	printf("scaling factor: %d\n", scale);
+ 
+ 	/* output in gaussian distribution benchmark */
+ 	if (use_gaussian)
+ 	{
+ 		int i;
+ 		printf("pgbench_account's aid selected with a truncated gaussian distribution\n");
+ 		printf("standard deviation threshold: %.5f\n", threshold);
+ 		printf("decile percents:");
+ 		for (i = 1; i <= 10; i++)
+ 			printf(" %.1f%%", 100.0 * gaussianProbability(i, 10.0, threshold));
+ 		printf("\n");
+ 		printf("probability of max/min percent of the range: %.1f%% %.1f%%\n",
+ 			  100.0 * gaussianProbability(50, 100, threshold),
+ 			  100.0 * gaussianProbability(100, 100, threshold));
+ 	}
+ 	/* output in exponential distribution benchmark */
+ 	else if (use_exponential)
+ 	{
+ 		int i;
+ 		printf("pgbench_account's aid selected with a truncated exponential distribution\n");
+ 		printf("exponential threshold: %.5f\n", threshold);
+ 		printf("decile percents:");
+ 		for (i = 1; i <= 10; i++)
+ 			printf(" %.1f%%",
+ 				   100.0 * exponentialProbability(i, 10, threshold));
+ 		printf("\n");
+ 		printf("probability of fist/last percent of the range: %.1f%% %.1f%%\n",
+ 			   100.0 * exponentialProbability(1, 100, threshold),
+ 			   100.0 * exponentialProbability(100, 100, threshold));
+ 	}
+ 
  	printf("query mode: %s\n", QUERYMODE[querymode]);
  	printf("number of clients: %d\n", nclients);
  	printf("number of threads: %d\n", nthreads);
***************
*** 2337,2342 **** main(int argc, char **argv)
--- 2408,2415 ----
  		{"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}
  	};
***************
*** 2617,2622 **** main(int argc, char **argv)
--- 2690,2714 ----
  				}
  #endif
  				break;
+ 			case 6:
+ 				use_gaussian = true;
+ 				threshold = atof(optarg);
+ 				if(threshold < MIN_GAUSSIAN_THRESHOLD)
+ 				{
+ 					fprintf(stderr, "--gaussian=NUM must be more than %f: %f\n",
+ 							MIN_GAUSSIAN_THRESHOLD, threshold);
+ 					exit(1);
+ 				}
+ 				break;
+ 			case 7:
+ 				use_exponential = true;
+ 				threshold = atof(optarg);
+ 				if(threshold <= 0.0)
+ 				{
+ 					fprintf(stderr, "--exponential=NUM must be more than 0.0\n");
+ 					exit(1);
+ 				}
+ 				break;
  			default:
  				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
  				exit(1);
***************
*** 2814,2819 **** main(int argc, char **argv)
--- 2906,2922 ----
  		}
  	}
  
+ 	/* set :threshold variable */
+ 	if(getVariable(&state[0], "threshold") == NULL)
+ 	{
+ 		snprintf(val, sizeof(val), "%lf", threshold);
+ 		for (i = 0; i < nclients; i++)
+ 		{
+ 			if (!putVariable(&state[i], "startup", "threshold", val))
+ 				exit(1);
+ 		}
+ 	}
+ 
  	if (!is_no_vacuum)
  	{
  		fprintf(stderr, "starting vacuum...");
***************
*** 2836,2860 **** main(int argc, char **argv)
  	srandom((unsigned int) INSTR_TIME_GET_MICROSEC(start_time));
  
  	/* process builtin SQL scripts */
! 	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;
! 
! 		default:
! 			break;
  	}
  
  	/* set up thread data structures */
--- 2939,2962 ----
  	srandom((unsigned int) INSTR_TIME_GET_MICROSEC(start_time));
  
  	/* process builtin SQL scripts */
! 	if (ttype < 3)
  	{
! 		char *fmt, *distribution, *queries;
! 		int ret;
! 		fmt = (ttype == 0)? tpc_b_fmt:
! 			  (ttype == 1)? select_only_fmt:
! 			  (ttype == 2)? simple_update_fmt: NULL;
! 		assert(fmt != NULL);
! 		distribution =
! 			use_gaussian? " gaussian :threshold":
! 			use_exponential? " exponential :threshold":
! 			"" /* default uniform case */ ;
! 		queries = pg_malloc(strlen(fmt) + strlen(distribution) + 1);
! 		ret = sprintf(queries, fmt, distribution);
! 		assert(ret >= 0);
! 		sql_files[0] = process_builtin(queries);
! 		num_files = 1;
! 		pg_free(queries);
  	}
  
  	/* set up thread data structures */
*** a/doc/src/sgml/pgbench.sgml
--- b/doc/src/sgml/pgbench.sgml
***************
*** 307,312 **** pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
--- 307,355 ----
       </varlistentry>
  
       <varlistentry>
+       <term><option>--exponential</option><replaceable>threshold</></term>
+       <listitem>
+        <para>
+          Run exponential distribution pgbench test using this threshold parameter.
+          The threshold controls the distribution of access frequency on the
+          <structname>pgbench_accounts</> table.
+          See the <literal>\setrandom</> documentation below for details about
+          the impact of the threshold value.
+          When set, this option applies to all test variants (<option>-N</> for
+          skipping updates, or <option>-S</> for selects).
+        </para>
+ 
+        <para>
+          When run, the output is expanded to show the distribution
+          depending on the <replaceable>threshold</> value:
+ 
+ <screen>
+ ...
+ pgbench_account's aid selected with a truncated exponential distribution
+ exponential threshold: 5.00000
+ decile percents: 39.6% 24.0% 14.6% 8.8% 5.4% 3.3% 2.0% 1.2% 0.7% 0.4%
+ probability of fist/last percent of the range: 4.9% 0.0%
+ ...
+ </screen>
+ 
+          The figures are to be interpreted as follows.
+          If the scaling factor is 10, there are 1,000,000 accounts in
+          <literal>pgbench_accounts</>.
+          The first decile, with <literal>aid</> from 1 to 100,000, is
+          drawn 39.6% of the time, that is about 4 times more than average.
+          The second decile, from 100,001 to 200,000 is drawn 24.0% of the time,
+          that is 2.4 times more than average.
+          Up to the last decile, from 900,001 to 1,000,000, which is drawn
+          0.4% of the time, well below average.
+          Moreover, the first percent of the range, that is <literal>aid</>
+          from 1 to 10,000, is drawn 4.9% of the time, this 4.9 times more
+          than average, and the last percent, with <literal>aid</>
+          from 990,001 to 1,000,000, is drawn less than 0.1% of the time.
+        </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</>
--- 363,411 ----
       </varlistentry>
  
       <varlistentry>
+       <term><option>--gaussian</option><replaceable>threshold</></term>
+       <listitem>
+        <para>
+          Run gaussian distribution pgbench test using this threshold parameter.
+          The threshold controls the distribution of access frequency on the
+          <structname>pgbench_accounts</> table.
+          See the <literal>\setrandom</> documentation below for details about
+          the impact of the threshold value.
+          When set, this option applies to all test variants (<option>-N</> for
+          skipping updates, or <option>-S</> for selects).
+        </para>
+ 
+        <para>
+          When run, the output is expanded to show the distribution
+          depending on the <replaceable>threshold</> value:
+ 
+ <screen>
+ ...
+ pgbench_account's aid selected with a truncated gaussian distribution
+ standard deviation threshold: 5.00000
+ decile percents: 0.0% 0.1% 2.1% 13.6% 34.1% 34.1% 13.6% 2.1% 0.1% 0.0%
+ probability of max/min percent of the range: 4.0% 0.0%
+ ...
+ </screen>
+ 
+          The figures are to be interpreted as follows.
+          If the scaling factor is 10, there are 1,000,000 accounts in
+          <literal>pgbench_accounts</>.
+          The first decile, with <literal>aid</> from 1 to 100,000, is
+          drawn less than 0.1% of the time.
+          The second, from 100,001 to 200,000 is drawn about 0.1% of the time...
+          up to the fifth decile, from 400,001 to 500,000, which
+          is drawn 34.1% of the time, about 3.4 times more thn average,
+          and then the gaussian curve is symmetric for the last five deciles.
+          Moreover, the first percent of the range, that is <literal>aid</>
+          from 50,001 to 60,000, is drawn 4.0% of the time, this 4.0 times more
+          than average, and the last percent, with <literal>aid</>
+          from 990,001 to 1,000,000, is drawn less than 0.1% of the time.
+        </para>
+       </listitem>
+      </varlistentry>
+ 
+      <varlistentry>
        <term><option>-j</option> <replaceable>threads</></term>
        <term><option>--jobs=</option><replaceable>threads</></term>
        <listitem>
