(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

Reply via email to