diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
new file mode 100644
index d607eca..dfc482f
*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 24,30 ****
      <para>
       All parameter names are case-insensitive. Every parameter takes a
       value of one of five types: boolean, integer, floating point,
!      string, or enum.
      </para>
  
      <itemizedlist>
--- 24,30 ----
      <para>
       All parameter names are case-insensitive. Every parameter takes a
       value of one of five types: boolean, integer, floating point,
!      string, or enum. Floating point values may be expressed as a percentage.
      </para>
  
      <itemizedlist>
*************** include_dir 'conf.d'
*** 2411,2418 ****
        </term>
        <listitem>
         <para>
!         Specifies the target of checkpoint completion, as a fraction of
!         total time between checkpoints. The default is 0.5.
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
         </para>
--- 2411,2418 ----
        </term>
        <listitem>
         <para>
!         Specifies the target of checkpoint completion, as a percentage of
!         total time between checkpoints. The default is 50%.
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
         </para>
*************** SELECT * FROM parent WHERE key = 2400;
*** 3589,3601 ****
        </term>
        <listitem>
         <para>
!         Sets the planner's estimate of the fraction of a cursor's rows that
!         will be retrieved.  The default is 0.1.  Smaller values of this
          setting bias the planner towards using <quote>fast start</> plans
          for cursors, which will retrieve the first few rows quickly while
          perhaps taking a long time to fetch all rows.  Larger values
          put more emphasis on the total estimated time.  At the maximum
!         setting of 1.0, cursors are planned exactly like regular queries,
          considering only the total estimated time and not how soon the
          first rows might be delivered.
         </para>
--- 3589,3601 ----
        </term>
        <listitem>
         <para>
!         Sets the planner's estimate of the percentage of a cursor's rows that
!         will be retrieved.  The default is 10%.  Smaller values of this
          setting bias the planner towards using <quote>fast start</> plans
          for cursors, which will retrieve the first few rows quickly while
          perhaps taking a long time to fetch all rows.  Larger values
          put more emphasis on the total estimated time.  At the maximum
!         setting of 100%, cursors are planned exactly like regular queries,
          considering only the total estimated time and not how soon the
          first rows might be delivered.
         </para>
*************** COPY postgres_log FROM '/full/path/to/lo
*** 5221,5230 ****
        </term>
        <listitem>
         <para>
!         Specifies a fraction of the table size to add to
          <varname>autovacuum_vacuum_threshold</varname>
          when deciding whether to trigger a <command>VACUUM</>.
!         The default is 0.2 (20% of table size).
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by
--- 5221,5230 ----
        </term>
        <listitem>
         <para>
!         Specifies a percentage of the table size to add to
          <varname>autovacuum_vacuum_threshold</varname>
          when deciding whether to trigger a <command>VACUUM</>.
!         The default is 20% of table size.
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by
*************** COPY postgres_log FROM '/full/path/to/lo
*** 5241,5250 ****
        </term>
        <listitem>
         <para>
!         Specifies a fraction of the table size to add to
          <varname>autovacuum_analyze_threshold</varname>
          when deciding whether to trigger an <command>ANALYZE</>.
!         The default is 0.1 (10% of table size).
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by
--- 5241,5250 ----
        </term>
        <listitem>
         <para>
!         Specifies a percentage of the table size to add to
          <varname>autovacuum_analyze_threshold</varname>
          when deciding whether to trigger an <command>ANALYZE</>.
!         The default is 10% of table size.
          This parameter can only be set in the <filename>postgresql.conf</>
          file or on the server command line.
          This setting can be overridden for individual tables by
diff --git a/src/backend/utils/misc/guc-file.l b/src/backend/utils/misc/guc-file.l
new file mode 100644
index 6dca5df..dc2171b
*** a/src/backend/utils/misc/guc-file.l
--- b/src/backend/utils/misc/guc-file.l
*************** UNIT_LETTER		[a-zA-Z]
*** 74,80 ****
  INTEGER			{SIGN}?({DIGIT}+|0x{HEXDIGIT}+){UNIT_LETTER}*
  
  EXPONENT		[Ee]{SIGN}?{DIGIT}+
! REAL			{SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}?
  
  LETTER			[A-Za-z_\200-\377]
  LETTER_OR_DIGIT [A-Za-z_0-9\200-\377]
--- 74,83 ----
  INTEGER			{SIGN}?({DIGIT}+|0x{HEXDIGIT}+){UNIT_LETTER}*
  
  EXPONENT		[Ee]{SIGN}?{DIGIT}+
! 
! FLOAT			{SIGN}?{DIGIT}*"."{DIGIT}*{EXPONENT}?
! PERCENT			{SIGN}?{DIGIT}*"."?{DIGIT}*"%"
! REAL			{FLOAT}|{PERCENT}
  
  LETTER			[A-Za-z_\200-\377]
  LETTER_OR_DIGIT [A-Za-z_0-9\200-\377]
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
new file mode 100644
index b1bff7f..fb67a90
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
*************** static struct config_real ConfigureNames
*** 2635,2643 ****
  
  	{
  		{"cursor_tuple_fraction", PGC_USERSET, QUERY_TUNING_OTHER,
! 			gettext_noop("Sets the planner's estimate of the fraction of "
  						 "a cursor's rows that will be retrieved."),
! 			NULL
  		},
  		&cursor_tuple_fraction,
  		DEFAULT_CURSOR_TUPLE_FRACTION, 0.0, 1.0,
--- 2635,2644 ----
  
  	{
  		{"cursor_tuple_fraction", PGC_USERSET, QUERY_TUNING_OTHER,
! 			gettext_noop("Sets the planner's estimate of the percentage of "
  						 "a cursor's rows that will be retrieved."),
! 			NULL,
! 			GUC_SHOW_PERCENT
  		},
  		&cursor_tuple_fraction,
  		DEFAULT_CURSOR_TUPLE_FRACTION, 0.0, 1.0,
*************** static struct config_real ConfigureNames
*** 2687,2694 ****
  
  	{
  		{"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
! 			gettext_noop("Number of tuple updates or deletes prior to vacuum as a fraction of reltuples."),
! 			NULL
  		},
  		&autovacuum_vac_scale,
  		0.2, 0.0, 100.0,
--- 2688,2696 ----
  
  	{
  		{"autovacuum_vacuum_scale_factor", PGC_SIGHUP, AUTOVACUUM,
! 			gettext_noop("Number of tuple updates or deletes prior to vacuum as a percentage of reltuples."),
! 			NULL,
! 			GUC_SHOW_PERCENT
  		},
  		&autovacuum_vac_scale,
  		0.2, 0.0, 100.0,
*************** static struct config_real ConfigureNames
*** 2696,2703 ****
  	},
  	{
  		{"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
! 			gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a fraction of reltuples."),
! 			NULL
  		},
  		&autovacuum_anl_scale,
  		0.1, 0.0, 100.0,
--- 2698,2706 ----
  	},
  	{
  		{"autovacuum_analyze_scale_factor", PGC_SIGHUP, AUTOVACUUM,
! 			gettext_noop("Number of tuple inserts, updates, or deletes prior to analyze as a percentage of reltuples."),
! 			NULL,
! 			GUC_SHOW_PERCENT
  		},
  		&autovacuum_anl_scale,
  		0.1, 0.0, 100.0,
*************** static struct config_real ConfigureNames
*** 2706,2713 ****
  
  	{
  		{"checkpoint_completion_target", PGC_SIGHUP, WAL_CHECKPOINTS,
! 			gettext_noop("Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval."),
! 			NULL
  		},
  		&CheckPointCompletionTarget,
  		0.5, 0.0, 1.0,
--- 2709,2717 ----
  
  	{
  		{"checkpoint_completion_target", PGC_SIGHUP, WAL_CHECKPOINTS,
! 			gettext_noop("Time spent flushing dirty buffers during checkpoint, as a percentage of checkpoint interval."),
! 			NULL,
! 			GUC_SHOW_PERCENT
  		},
  		&CheckPointCompletionTarget,
  		0.5, 0.0, 1.0,
*************** parse_int(const char *value, int *result
*** 5253,5258 ****
--- 5257,5263 ----
  
  /*
   * Try to parse value as a floating point number in the usual format.
+  * If the string ends in '%' divide by 100.
   * If the string parses okay, return true, else false.
   * If okay and result is not NULL, return the value in *result.
   */
*************** parse_real(const char *value, double *re
*** 5270,5275 ****
--- 5275,5287 ----
  	if (endptr == value || errno == ERANGE)
  		return false;
  
+ 	/* Check for percentage. */
+ 	if (*endptr == '%')
+ 	{
+ 		val /= 100.0;
+ 		endptr++;
+ 	}
+ 
  	/* allow whitespace after number */
  	while (isspace((unsigned char) *endptr))
  		endptr++;
*************** _ShowOption(struct config_generic * reco
*** 8208,8215 ****
  					val = (*conf->show_hook) ();
  				else
  				{
! 					snprintf(buffer, sizeof(buffer), "%g",
! 							 *conf->variable);
  					val = buffer;
  				}
  			}
--- 8220,8235 ----
  					val = (*conf->show_hook) ();
  				else
  				{
! 					if (record->flags & GUC_SHOW_PERCENT)
! 					{
! 						snprintf(buffer, sizeof(buffer), "%g%%",
! 								*conf->variable * 100.0);
! 					}
! 					else
! 					{
! 						snprintf(buffer, sizeof(buffer), "%g",
! 								*conf->variable);
! 					}
  					val = buffer;
  				}
  			}
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
new file mode 100644
index b053659..0352c2d
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 199,205 ****
  
  #checkpoint_segments = 3		# in logfile segments, min 1, 16MB each
  #checkpoint_timeout = 5min		# range 30s-1h
! #checkpoint_completion_target = 0.5	# checkpoint target duration, 0.0 - 1.0
  #checkpoint_warning = 30s		# 0 disables
  
  # - Archiving -
--- 199,205 ----
  
  #checkpoint_segments = 3		# in logfile segments, min 1, 16MB each
  #checkpoint_timeout = 5min		# range 30s-1h
! #checkpoint_completion_target = 50%	# checkpoint target duration, 0-100%
  #checkpoint_warning = 30s		# 0 disables
  
  # - Archiving -
***************
*** 303,309 ****
  
  #default_statistics_target = 100	# range 1-10000
  #constraint_exclusion = partition	# on, off, or partition
! #cursor_tuple_fraction = 0.1		# range 0.0-1.0
  #from_collapse_limit = 8
  #join_collapse_limit = 8		# 1 disables collapsing of explicit
  					# JOIN clauses
--- 303,309 ----
  
  #default_statistics_target = 100	# range 1-10000
  #constraint_exclusion = partition	# on, off, or partition
! #cursor_tuple_fraction = 10%		# range 0-100%
  #from_collapse_limit = 8
  #join_collapse_limit = 8		# 1 disables collapsing of explicit
  					# JOIN clauses
***************
*** 483,490 ****
  					# vacuum
  #autovacuum_analyze_threshold = 50	# min number of row updates before
  					# analyze
! #autovacuum_vacuum_scale_factor = 0.2	# fraction of table size before vacuum
! #autovacuum_analyze_scale_factor = 0.1	# fraction of table size before analyze
  #autovacuum_freeze_max_age = 200000000	# maximum XID age before forced vacuum
  					# (change requires restart)
  #autovacuum_multixact_freeze_max_age = 400000000	# maximum multixact age
--- 483,490 ----
  					# vacuum
  #autovacuum_analyze_threshold = 50	# min number of row updates before
  					# analyze
! #autovacuum_vacuum_scale_factor = 20%	# percent of table size before vacuum
! #autovacuum_analyze_scale_factor = 10%	# percent of table size before analyze
  #autovacuum_freeze_max_age = 200000000	# maximum XID age before forced vacuum
  					# (change requires restart)
  #autovacuum_multixact_freeze_max_age = 400000000	# maximum multixact age
diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h
new file mode 100644
index 80813d2..fd7bde5
*** a/src/include/utils/guc.h
--- b/src/include/utils/guc.h
*************** typedef enum
*** 215,220 ****
--- 215,221 ----
  #define GUC_NOT_WHILE_SEC_REST	0x8000	/* can't set if security restricted */
  #define GUC_DISALLOW_IN_AUTO_FILE	0x00010000	/* can't set in
  												 * PG_AUTOCONF_FILENAME */
+ #define GUC_SHOW_PERCENT		0x00020000	/* Display as percent. */
  
  /* GUC vars that are actually declared in guc.c, rather than elsewhere */
  extern bool log_duration;
diff --git a/src/test/regress/expected/guc.out b/src/test/regress/expected/guc.out
new file mode 100644
index 4f0065c..95feb8c
*** a/src/test/regress/expected/guc.out
--- b/src/test/regress/expected/guc.out
*************** SHOW datestyle;
*** 9,14 ****
--- 9,15 ----
  -- SET to some nondefault value
  SET vacuum_cost_delay TO 40;
  SET datestyle = 'ISO, YMD';
+ SET cursor_tuple_fraction = '15%';
  SHOW vacuum_cost_delay;
   vacuum_cost_delay 
  -------------------
*************** SHOW datestyle;
*** 21,26 ****
--- 22,33 ----
   ISO, YMD
  (1 row)
  
+ SHOW cursor_tuple_fraction;
+  cursor_tuple_fraction 
+ -----------------------
+  15%
+ (1 row)
+ 
  SELECT '2006-08-13 12:34:56'::timestamptz;
        timestamptz       
  ------------------------
diff --git a/src/test/regress/sql/guc.sql b/src/test/regress/sql/guc.sql
new file mode 100644
index 3de8a6b..4fef222
*** a/src/test/regress/sql/guc.sql
--- b/src/test/regress/sql/guc.sql
*************** SHOW datestyle;
*** 5,12 ****
--- 5,14 ----
  -- SET to some nondefault value
  SET vacuum_cost_delay TO 40;
  SET datestyle = 'ISO, YMD';
+ SET cursor_tuple_fraction = '15%';
  SHOW vacuum_cost_delay;
  SHOW datestyle;
+ SHOW cursor_tuple_fraction;
  SELECT '2006-08-13 12:34:56'::timestamptz;
  
  -- SET LOCAL has no effect outside of a transaction
