diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index 64b043b48a..1dea6e4b17 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -1014,6 +1014,14 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
        <entry>an integer between <literal>1</> and <literal>10</></>
       </row>
       <row>
+        <entry><literal><function>random_zipfian(<replaceable>lb</>, <replaceable>ub</>, <replaceable>parameter</>)</></></>
+        <entry>integer</>
+        <entry> Zipfian-distributed random integer in <literal>[lb, ub]</>,
+              see below</>
+        <entry><literal>random_zipfian(1, 10, 1.2)</></>
+        <entry>an integer between <literal>1</> and <literal>10</></>
+      </row>
+      <row>
        <entry><literal><function>sqrt(<replaceable>x</>)</></></>
        <entry>double</>
        <entry>square root</>
@@ -1094,6 +1102,24 @@ f(x) = PHI(2.0 * parameter * (x - mu) / (max - min + 1)) /
       of the Box-Muller transform.
      </para>
     </listitem>
+
+    <listitem>
+        <para>
+          For Zipfian distribution, <replaceable>parameter</> 
+          defines how skewed the distribution. A physical sense of this parameter
+          is following: <literal>1</> generated <literal>N</> times, 
+          <literal>2</> generated <literal>2 ^ parameter</> less, 
+          <literal>3</> generated <literal>3 ^ parameter</> less, ...
+          <literal> X </> generated <literal>X ^ parameter</> less times.
+        </para>
+        <para>
+          Intuitively, the larger the <replaceable>parameter</>, the more
+          frequently value values to the beginning of the interval are drawn. 
+          The closer to 0 <replaceable>parameter</> is, 
+          the flatter (more uniform) the access distribution.
+
+        </para>
+    </listitem>
    </itemizedlist>
 
   <para>
diff --git a/src/bin/pgbench/exprparse.y b/src/bin/pgbench/exprparse.y
index b3a2d9bfd3..25d5ad48e5 100644
--- a/src/bin/pgbench/exprparse.y
+++ b/src/bin/pgbench/exprparse.y
@@ -191,6 +191,9 @@ static const struct
 	{
 		"random_exponential", 3, PGBENCH_RANDOM_EXPONENTIAL
 	},
+	{
+		"random_zipfian", 3, PGBENCH_RANDOM_ZIPFIAN
+	},
 	/* keep as last array element */
 	{
 		NULL, 0, 0
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 4d364a1db4..9e515abe9b 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -94,6 +94,7 @@ static int	pthread_join(pthread_t th, void **thread_return);
 #define DEFAULT_NXACTS	10		/* default nxacts */
 
 #define MIN_GAUSSIAN_PARAM		2.0 /* minimum parameter for gauss */
+#define MIN_ZIPFIAN_PARAM		1.0000001 /* minimum parameter for zipfian */
 
 int			nxacts = 0;			/* number of transactions per client */
 int			duration = 0;		/* duration in seconds */
@@ -184,6 +185,14 @@ char	   *dbName;
 char	   *logfile_prefix = NULL;
 const char *progname;
 
+/* Variables used in zipfian_random */
+double		zipf_zetan;				/* zeta(n) */
+double		zipf_prev_theta;		/* theta parameter of previous execution */
+double		zipf_prev_nitems;		/* n(ub - lb + 1) parameter of previous execution */
+double		zipf_alpha;
+double		zipf_beta;
+double		zipf_eta;
+
 #define WSEP '@'				/* weight separator */
 
 volatile bool timer_exceeded = false;	/* flag from signal handler */
@@ -737,6 +746,58 @@ getPoissonRand(TState *thread, int64 center)
 	return (int64) (-log(uniform) * ((double) center) + 0.5);
 }
 
+/* helper function for getZipfianRand */
+static double 
+zeta(int64 n, double theta)
+{
+	int			i;
+	double		ans = 0.0;
+
+	for (i = 1; i <= n; i++)
+		ans += pow(1. / (double)i, theta);
+	return (ans);
+}
+
+/* helper function for getZipfianRand. Computes random variable in range 1..n */
+static int64 
+zipfn(TState *thread, int64 n, double theta)
+{
+	double		u = pg_erand48(thread->random_state);
+	double		uz = u * zipf_zetan;
+
+	if (uz < 1.)
+		return 1;
+	if (uz < 1 + zipf_beta)
+		return 2;
+	return 1 + (int64)(n * pow(zipf_eta * u - zipf_eta + 1., zipf_alpha));
+}
+
+/* random number generator: zipfian distribution from min to max inclusive */
+static int64
+getZipfianRand(TState *thread, int64 min, int64 max, double theta)
+{
+	Assert(theta > MIN_ZIPFIAN_PARAM);
+
+	int64		n = max - min + 1;
+	double		zipf_zeta2;
+
+	/* update cached variables if current parameters are different from previous */
+	if (n != zipf_prev_nitems || theta != zipf_prev_theta)
+	{
+		zipf_prev_theta = theta;
+		zipf_prev_nitems = n;
+		
+		zipf_zeta2 = zeta(2, theta);
+		zipf_zetan = zeta(n, theta);
+
+		zipf_alpha = 1. / (1 - theta);
+		zipf_beta = pow(0.5, theta);
+		zipf_eta = (1. - pow(2. / n, 1 - theta)) / (1. - zipf_zeta2 / zipf_zetan);
+	}
+
+	return min + zipfn(thread, n, theta) - 1;
+}
+
 /*
  * Initialize the given SimpleStats struct to all zeroes
  */
@@ -1567,6 +1628,7 @@ evalFunc(TState *thread, CState *st,
 		case PGBENCH_RANDOM:
 		case PGBENCH_RANDOM_EXPONENTIAL:
 		case PGBENCH_RANDOM_GAUSSIAN:
+		case PGBENCH_RANDOM_ZIPFIAN:
 			{
 				int64		imin,
 							imax;
@@ -1617,6 +1679,18 @@ evalFunc(TState *thread, CState *st,
 						setIntValue(retval,
 									getGaussianRand(thread, imin, imax, param));
 					}
+					else if (func == PGBENCH_RANDOM_ZIPFIAN)
+					{
+						if (param <= MIN_ZIPFIAN_PARAM)
+						{
+							fprintf(stderr,
+									"zipfian parameter must be greater than %f "
+									"(not %f)\n", MIN_ZIPFIAN_PARAM, param);
+							return false;
+						}
+						setIntValue(retval,
+									getZipfianRand(thread, imin, imax, param));
+					}
 					else		/* exponential */
 					{
 						if (param <= 0.0)
diff --git a/src/bin/pgbench/pgbench.h b/src/bin/pgbench/pgbench.h
index abc13e9463..1a29f1260c 100644
--- a/src/bin/pgbench/pgbench.h
+++ b/src/bin/pgbench/pgbench.h
@@ -75,7 +75,8 @@ typedef enum PgBenchFunction
 	PGBENCH_SQRT,
 	PGBENCH_RANDOM,
 	PGBENCH_RANDOM_GAUSSIAN,
-	PGBENCH_RANDOM_EXPONENTIAL
+	PGBENCH_RANDOM_EXPONENTIAL,
+	PGBENCH_RANDOM_ZIPFIAN
 } PgBenchFunction;
 
 typedef struct PgBenchExpr PgBenchExpr;
