diff --git a/doc/src/sgml/ref/pgbench.sgml b/doc/src/sgml/ref/pgbench.sgml
index 03e1212..8e3d090 100644
--- a/doc/src/sgml/ref/pgbench.sgml
+++ b/doc/src/sgml/ref/pgbench.sgml
@@ -25,6 +25,12 @@
   </cmdsynopsis>
   <cmdsynopsis>
    <command>pgbench</command>
+   <arg choice="plain"><option>--custom-initailize={<replaceable>custom_init_command</replaceable> [, ...]}</option></arg>
+   <arg rep="repeat"><replaceable>option</replaceable></arg>
+   <arg choice="opt"><replaceable>dbname</replaceable></arg>
+  </cmdsynopsis>
+  <cmdsynopsis>
+   <command>pgbench</command>
    <arg rep="repeat"><replaceable>option</replaceable></arg>
    <arg choice="opt"><replaceable>dbname</replaceable></arg>
   </cmdsynopsis>
@@ -72,10 +78,10 @@ tps = 85.296346 (excluding connections establishing)
   <para>
    The default TPC-B-like transaction test requires specific tables to be
    set up beforehand.  <application>pgbench</> should be invoked with
-   the <option>-i</> (initialize) option to create and populate these
-   tables.  (When you are testing a custom script, you don't need this
-   step, but will instead need to do whatever setup your test needs.)
-   Initialization looks like:
+   the <option>-i</> (initialize) or <option>--custom-initialize</> option
+   to create and populate these tables.  (When you are testing a custom
+   script, you don't need this step, but will instead need to do whatever
+   setup your test needs.) Initialization looks like:
 
 <programlisting>
 pgbench -i <optional> <replaceable>other-options</> </optional> <replaceable>dbname</>
@@ -211,6 +217,64 @@ pgbench <optional> <replaceable>options</> </optional> <replaceable>dbname</>
      </varlistentry>
 
      <varlistentry>
+      <term><option>--custom-initialize={<replaceable>custom_init_command</replaceable> [, ...]}</option></term>
+      <listitem>
+       <para>
+        Required to invoke custom initialization mode.
+        <replaceable>custom_init_command</replaceable> specified custom
+        initialization commands for the initialization. Each command is invoked
+        in the specified order. The supported commands are:
+
+        <variablelist>
+         <varlistentry>
+          <term><literal>create_table</literal></term>
+          <listitem>
+           <para>
+            Create four tables <structname>pgbench_accounts</>,
+            <structname>pgbench_branches</>, <structname>pgbench_history</>,
+            and <structname>pgbench_tellers</>, destroying any existing
+            tables of these names.
+           </para>
+          </listitem>
+         </varlistentry>
+         <varlistentry>
+          <term><literal>load_data</literal></term>
+          <listitem>
+           <para>
+            Load data to standard tables.
+           </para>
+          </listitem>
+         </varlistentry>
+         <varlistentry>
+          <term><literal>vacuum</literal></term>
+          <listitem>
+           <para>
+            Invoke vacuum on standard tables.
+           </para>
+          </listitem>
+         </varlistentry>
+         <varlistentry>
+          <term><literal>create_pkey</literal></term>
+          <listitem>
+           <para>
+            Create primary keys on standard tables.
+           </para>
+          </listitem>
+         </varlistentry>
+         <varlistentry>
+          <term><literal>create_fkey</literal></term>
+          <listitem>
+           <para>
+            Create foreign keys constraints between the standard tables.
+           </para>
+          </listitem>
+         </varlistentry>
+        </variablelist>
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
       <term><option>--foreign-keys</option></term>
       <listitem>
        <para>
diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c
index 4d364a1..8cb9d3a 100644
--- a/src/bin/pgbench/pgbench.c
+++ b/src/bin/pgbench/pgbench.c
@@ -36,6 +36,7 @@
 #include "getopt_long.h"
 #include "libpq-fe.h"
 #include "portability/instr_time.h"
+#include "fe_utils/simple_list.h"
 
 #include <ctype.h>
 #include <float.h>
@@ -445,7 +446,6 @@ static const BuiltinScript builtin_script[] =
 	}
 };
 
-
 /* Function prototypes */
 static void setIntValue(PgBenchValue *pv, int64 ival);
 static void setDoubleValue(PgBenchValue *pv, double dval);
@@ -458,7 +458,12 @@ static void pgbench_error(const char *fmt,...) pg_attribute_printf(1, 2);
 static void addScript(ParsedScript script);
 static void *threadRun(void *arg);
 static void setalarm(int seconds);
-
+static bool parseCustomInitialize(char *rawstring, SimpleStringList *list);
+static void initCreateTables(PGconn *con);
+static void initLoadData(PGconn *con);
+static void initVacuum(PGconn *con);
+static void initCreatePKeys(PGconn *con);
+static void initCreateFKeys(PGconn *con);
 
 /* callback functions for our flex lexer */
 static const PsqlScanCallbacks pgbench_callbacks = {
@@ -484,6 +489,8 @@ usage(void)
 		   "                           create indexes in the specified tablespace\n"
 		   "  --tablespace=TABLESPACE  create tables in the specified tablespace\n"
 		   "  --unlogged-tables        create tables as unlogged tables\n"
+		   "  --custom-initilize={[create_table|load_data|vacuum|create_pkey|create_fkey] [, ...]}\n"
+		   "                           invokes custom initialization\n"
 		   "\nOptions to select what to run:\n"
 		   "  -b, --builtin=NAME[@W]   add builtin script NAME weighted at W (default: 1)\n"
 		   "                           (use \"-b list\" to list available scripts)\n"
@@ -2566,9 +2573,78 @@ disconnect_all(CState *state, int length)
 	}
 }
 
-/* create tables and setup data */
+
+/*
+ * Split rawstring by ',' and parse the custom initialization
+ * command; return a list of custom initialization command.
+ */
+static bool
+parseCustomInitialize(char *rawstring, SimpleStringList *list)
+{
+	char	*nextp = rawstring;
+	bool	done = false;
+
+	while (isspace(*nextp))
+		nextp++;	/* skip leading whitespace */
+
+	do
+	{
+		char	*curname;
+		char	*parsedname;
+		char	*endp;
+		int		len;
+
+		curname = nextp;
+		while (*nextp && *nextp != ',' && !isspace(*nextp))
+			nextp++;
+		endp = nextp;
+		if (curname == nextp)
+			return false;
+
+		len = endp  - curname;
+		parsedname = pg_malloc(sizeof(char) * len + 1);
+		strncpy(parsedname, curname, len);
+
+		while (isspace(*nextp))
+			nextp++;	/* skip trailing whitespace */
+		if (*nextp == ',')
+		{
+			nextp++;
+			while (isspace(*nextp))
+				nextp++;		/* skip leading whitespace for next */
+			/* we expect another name, so done remains false */
+		}
+		else if (*nextp == '\0')
+			done = true;
+		else
+			return false;	/* invalid syntax */
+
+		*endp = '\0';
+
+		if (!(pg_strncasecmp(parsedname, "create_table", 12) == 0 ||
+			  pg_strncasecmp(parsedname, "load_data", 9) == 0 ||
+			  pg_strncasecmp(parsedname, "vacuum", 6) == 0 ||
+			  pg_strncasecmp(parsedname, "create_pkey", 12) == 0 ||
+			  pg_strncasecmp(parsedname, "create_fkey", 12) == 0))
+		{
+			fprintf(stderr, "invalid custom initialization script command \"%s\"\n", parsedname);
+			return false;
+		}
+
+		/* FInished current name, add it to list */
+		simple_string_list_append(list, parsedname);
+
+		/* Loop back if we didn't reach end of string */
+	} while(!done);
+
+	return true;
+}
+
+/*
+ * Create tables, remove old tables if exist.
+ */
 static void
-init(bool is_no_vacuum)
+initCreateTables(PGconn *con)
 {
 /*
  * The scale factor at/beyond which 32-bit integers are insufficient for
@@ -2623,34 +2699,8 @@ init(bool is_no_vacuum)
 			1
 		}
 	};
-	static const char *const DDLINDEXes[] = {
-		"alter table pgbench_branches add primary key (bid)",
-		"alter table pgbench_tellers add primary key (tid)",
-		"alter table pgbench_accounts add primary key (aid)"
-	};
-	static const char *const DDLKEYs[] = {
-		"alter table pgbench_tellers add foreign key (bid) references pgbench_branches",
-		"alter table pgbench_accounts add foreign key (bid) references pgbench_branches",
-		"alter table pgbench_history add foreign key (bid) references pgbench_branches",
-		"alter table pgbench_history add foreign key (tid) references pgbench_tellers",
-		"alter table pgbench_history add foreign key (aid) references pgbench_accounts"
-	};
 
-	PGconn	   *con;
-	PGresult   *res;
-	char		sql[256];
-	int			i;
-	int64		k;
-
-	/* used to track elapsed time and estimate of the remaining time */
-	instr_time	start,
-				diff;
-	double		elapsed_sec,
-				remaining_sec;
-	int			log_interval = 1;
-
-	if ((con = doConnect()) == NULL)
-		exit(1);
+	int i;
 
 	for (i = 0; i < lengthof(DDLs); i++)
 	{
@@ -2687,6 +2737,95 @@ init(bool is_no_vacuum)
 
 		executeStatement(con, buffer);
 	}
+}
+
+/* Invoke vacuum on all tables */
+static void
+initVacuum(PGconn *con)
+{
+	fprintf(stderr, "vacuum...\n");
+	executeStatement(con, "vacuum analyze pgbench_branches");
+	executeStatement(con, "vacuum analyze pgbench_tellers");
+	executeStatement(con, "vacuum analyze pgbench_accounts");
+	executeStatement(con, "vacuum analyze pgbench_history");
+}
+
+/*
+ * Create foreign key constraints between the standard tables
+ */
+static void
+initCreateFKeys(PGconn *con)
+{
+	static const char *const DDLKEYs[] = {
+		"alter table pgbench_tellers add foreign key (bid) references pgbench_branches",
+		"alter table pgbench_accounts add foreign key (bid) references pgbench_branches",
+		"alter table pgbench_history add foreign key (bid) references pgbench_branches",
+		"alter table pgbench_history add foreign key (tid) references pgbench_tellers",
+		"alter table pgbench_history add foreign key (aid) references pgbench_accounts"
+	};
+
+	int i;
+
+	fprintf(stderr, "set foreign keys...\n");
+	for (i = 0; i < lengthof(DDLKEYs); i++)
+	{
+		executeStatement(con, DDLKEYs[i]);
+	}
+}
+
+/*
+ * Create primary keys on three tables; pgbench_accounts,
+ * pgbench_branches and pgbench_tellers.
+ */
+static void
+initCreatePKeys(PGconn *con)
+{
+	static const char *const DDLINDEXes[] = {
+		"alter table pgbench_branches add primary key (bid)",
+		"alter table pgbench_tellers add primary key (tid)",
+		"alter table pgbench_accounts add primary key (aid)"
+	};
+	int i;
+
+	fprintf(stderr, "set primary keys...\n");
+	for (i = 0; i < lengthof(DDLINDEXes); i++)
+	{
+		char		buffer[256];
+
+		strlcpy(buffer, DDLINDEXes[i], sizeof(buffer));
+
+		if (index_tablespace != NULL)
+		{
+			char	   *escape_tablespace;
+
+			escape_tablespace = PQescapeIdentifier(con, index_tablespace,
+												   strlen(index_tablespace));
+			snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer),
+					 " using index tablespace %s", escape_tablespace);
+			PQfreemem(escape_tablespace);
+		}
+
+		executeStatement(con, buffer);
+	}
+}
+
+/*
+ * Fill the standard table with some data.
+ */
+static void
+initLoadData(PGconn *con)
+{
+	char		sql[256];
+	PGresult   *res;
+	int			i;
+	int64		k;
+
+	/* used to track elapsed time and estimate of the remaining time */
+	instr_time	start,
+				diff;
+	double		elapsed_sec,
+				remaining_sec;
+	int			log_interval = 1;
 
 	executeStatement(con, "begin");
 
@@ -2792,52 +2931,68 @@ init(bool is_no_vacuum)
 		exit(1);
 	}
 	executeStatement(con, "commit");
+}
 
-	/* vacuum */
-	if (!is_no_vacuum)
+/* invoke each custom initialization commands */
+static void
+custom_init(SimpleStringList custom_initialize_list)
+{
+	SimpleStringListCell *cell;
+	PGconn	   *con;
+
+	if ((con = doConnect()) == NULL)
+		exit(1);
+
+	for (cell = custom_initialize_list.head; cell; cell = cell->next)
 	{
-		fprintf(stderr, "vacuum...\n");
-		executeStatement(con, "vacuum analyze pgbench_branches");
-		executeStatement(con, "vacuum analyze pgbench_tellers");
-		executeStatement(con, "vacuum analyze pgbench_accounts");
-		executeStatement(con, "vacuum analyze pgbench_history");
+		if (pg_strncasecmp(cell->val, "create_table", 12) == 0)
+			initCreateTables(con);
+		else if (pg_strncasecmp(cell->val, "load_data", 9) == 0)
+			initLoadData(con);
+		else if (pg_strncasecmp(cell->val, "vacuum", 6) == 0)
+			initVacuum(con);
+		else if (pg_strncasecmp(cell->val, "create_pkey", 11) == 0)
+			initCreatePKeys(con);
+		else if (pg_strncasecmp(cell->val, "create_fkey", 11) == 0)
+			initCreateFKeys(con);
+		else
+		{
+			fprintf(stderr, "invalid custom initialization script command \"%s\"\n", cell->val);
+			fprintf(stderr, "possible commands are: \"create_table\", \"load_data\", \"vacuum\", \"create_pkeys\", \"create_fkyes\"\n");
+			PQfinish(con);
+			exit(1);
+		}
 	}
 
-	/*
-	 * create indexes
-	 */
-	fprintf(stderr, "set primary keys...\n");
-	for (i = 0; i < lengthof(DDLINDEXes); i++)
-	{
-		char		buffer[256];
+	fprintf(stderr, "done.\n");
+	PQfinish(con);
+}
 
-		strlcpy(buffer, DDLINDEXes[i], sizeof(buffer));
+/* create tables and setup data */
+static void
+init(bool is_no_vacuum)
+{
+	PGconn	   *con;
 
-		if (index_tablespace != NULL)
-		{
-			char	   *escape_tablespace;
+	if ((con = doConnect()) == NULL)
+		exit(1);
 
-			escape_tablespace = PQescapeIdentifier(con, index_tablespace,
-												   strlen(index_tablespace));
-			snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer),
-					 " using index tablespace %s", escape_tablespace);
-			PQfreemem(escape_tablespace);
-		}
+	/* create tables */
+	initCreateTables(con);
 
-		executeStatement(con, buffer);
-	}
+	/* load data */
+	initLoadData(con);
 
-	/*
-	 * create foreign keys
-	 */
+	/* vacuum */
+	if (!is_no_vacuum)
+		initVacuum(con);
+
+	/* create indexes */
+	initCreatePKeys(con);
+
+	/* create foreign keys */
 	if (foreign_keys)
-	{
-		fprintf(stderr, "set foreign keys...\n");
-		for (i = 0; i < lengthof(DDLKEYs); i++)
-		{
-			executeStatement(con, DDLKEYs[i]);
-		}
-	}
+		initCreateFKeys(con);
 
 	fprintf(stderr, "done.\n");
 	PQfinish(con);
@@ -3623,6 +3778,7 @@ main(int argc, char **argv)
 		{"log", no_argument, NULL, 'l'},
 		{"latency-limit", required_argument, NULL, 'L'},
 		{"no-vacuum", no_argument, NULL, 'n'},
+		{"no-primary-keys", no_argument, NULL, 'I'},
 		{"port", required_argument, NULL, 'p'},
 		{"progress", required_argument, NULL, 'P'},
 		{"protocol", required_argument, NULL, 'M'},
@@ -3645,12 +3801,16 @@ main(int argc, char **argv)
 		{"aggregate-interval", required_argument, NULL, 5},
 		{"progress-timestamp", no_argument, NULL, 6},
 		{"log-prefix", required_argument, NULL, 7},
+		{"custom-initialize", required_argument, NULL, 8},
 		{NULL, 0, NULL, 0}
 	};
 
 	int			c;
 	int			is_init_mode = 0;	/* initialize mode? */
+	int			is_initialize_suite = 0;
+	int			is_custom_initialize = 0;
 	int			is_no_vacuum = 0;	/* no vacuum at all before testing? */
+	SimpleStringList custom_initialize_list = {NULL, NULL};
 	int			do_vacuum_accounts = 0; /* do vacuum accounts before testing? */
 	int			optindex;
 	bool		scale_given = false;
@@ -3719,6 +3879,7 @@ main(int argc, char **argv)
 		{
 			case 'i':
 				is_init_mode++;
+				is_initialize_suite++;
 				break;
 			case 'h':
 				pghost = pg_strdup(optarg);
@@ -3991,6 +4152,20 @@ main(int argc, char **argv)
 				benchmarking_option_set = true;
 				logfile_prefix = pg_strdup(optarg);
 				break;
+			case 8:
+				{
+					char *rawstring = pg_strdup(optarg);
+
+					if (!parseCustomInitialize(rawstring, &custom_initialize_list))
+					{
+						fprintf(stderr, "invalid syntax of custom initialization \"%s\"\n",
+								optarg);
+						exit(1);
+					}
+					is_init_mode++;
+					is_custom_initialize++;
+				}
+				break;
 			default:
 				fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname);
 				exit(1);
@@ -4052,7 +4227,16 @@ main(int argc, char **argv)
 			exit(1);
 		}
 
-		init(is_no_vacuum);
+		if (is_initialize_suite && is_custom_initialize)
+		{
+			fprintf(stderr, "cannot initialize specific custom initialize mode and initialize mode at the same time\n");
+			exit(1);
+		}
+
+		if (is_custom_initialize)
+			custom_init(custom_initialize_list);
+		else
+			init(is_no_vacuum);
 		exit(0);
 	}
 	else
