diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index e82a53a..cf3fb1b 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -624,7 +624,8 @@ CREATE VIEW pg_stat_activity AS
             S.state,
             S.backend_xid,
             s.backend_xmin,
-            S.query
+            S.query,
+			S.percent_complete
     FROM pg_database D, pg_stat_get_activity(NULL) AS S, pg_authid U
     WHERE S.datid = D.oid AND
             S.usesysid = U.oid;
diff --git a/src/backend/commands/vacuumlazy.c b/src/backend/commands/vacuumlazy.c
index a01cfb4..04c8547 100644
--- a/src/backend/commands/vacuumlazy.c
+++ b/src/backend/commands/vacuumlazy.c
@@ -439,7 +439,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 			   Relation *Irel, int nindexes, bool scan_all)
 {
 	BlockNumber nblocks,
-				blkno;
+				blkno,
+				total_pages_scanned;
 	HeapTupleData tuple;
 	char	   *relname;
 	BlockNumber empty_pages,
@@ -456,6 +457,8 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 	bool		skipping_all_visible_blocks;
 	xl_heap_freeze_tuple *frozen;
 	StringInfoData buf;
+	TimestampTz previous_time;
+	TimestampTz current_time;
 
 	pg_rusage_init(&ru0);
 
@@ -471,12 +474,13 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 	indstats = (IndexBulkDeleteResult **)
 		palloc0(nindexes * sizeof(IndexBulkDeleteResult *));
 
-	nblocks = RelationGetNumberOfBlocks(onerel);
+	total_pages_scanned = nblocks = RelationGetNumberOfBlocks(onerel);
 	vacrelstats->rel_pages = nblocks;
 	vacrelstats->scanned_pages = 0;
 	vacrelstats->nonempty_pages = 0;
 	vacrelstats->latestRemovedXid = InvalidTransactionId;
 
+	previous_time = GetCurrentTimestamp();
 	lazy_space_alloc(vacrelstats, nblocks);
 	frozen = palloc(sizeof(xl_heap_freeze_tuple) * MaxHeapTuplesPerPage);
 
@@ -520,7 +524,10 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 		vacuum_delay_point();
 	}
 	if (next_not_all_visible_block >= SKIP_PAGES_THRESHOLD)
+	{
 		skipping_all_visible_blocks = true;
+		total_pages_scanned = total_pages_scanned - next_not_all_visible_block;
+	}
 	else
 		skipping_all_visible_blocks = false;
 
@@ -559,7 +566,10 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 			 * following blocks.
 			 */
 			if (next_not_all_visible_block - blkno > SKIP_PAGES_THRESHOLD)
+			{
 				skipping_all_visible_blocks = true;
+				total_pages_scanned = total_pages_scanned - (next_not_all_visible_block - blkno);
+			}
 			else
 				skipping_all_visible_blocks = false;
 			all_visible_according_to_vm = false;
@@ -1062,6 +1072,17 @@ lazy_scan_heap(Relation onerel, LVRelStats *vacrelstats,
 		 */
 		if (vacrelstats->num_dead_tuples == prev_dead_count)
 			RecordPageWithFreeSpace(onerel, blkno, freespace);
+
+		/*
+		 * Reporting vacuum progress to statistics collector
+		 */
+		if (pgstat_track_progress == 0 || (pgstat_track_progress > 0 &&
+				TimestampDifferenceExceeds(previous_time, current_time = GetCurrentTimestamp(),
+											pgstat_track_progress)))
+		{
+			previous_time = current_time;
+			pgstat_report_progress(total_pages_scanned, vacrelstats->scanned_pages);
+		}
 	}
 
 	pfree(frozen);
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index e9fbc38..e7ed315 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -67,6 +67,7 @@
 #include "utils/tqual.h"
 
 
+
 /* ----------
  * Timer definitions.
  * ----------
@@ -108,6 +109,7 @@ bool		pgstat_track_activities = false;
 bool		pgstat_track_counts = false;
 int			pgstat_track_functions = TRACK_FUNC_OFF;
 int			pgstat_track_activity_query_size = 1024;
+int 		pgstat_track_progress;
 
 /* ----------
  * Built from GUC parameter
@@ -2720,7 +2722,7 @@ pgstat_bestart(void)
 	beentry->st_clienthostname[NAMEDATALEN - 1] = '\0';
 	beentry->st_appname[NAMEDATALEN - 1] = '\0';
 	beentry->st_activity[pgstat_track_activity_query_size - 1] = '\0';
-
+	beentry->percent_complete = 0;
 	pgstat_increment_changecount_after(beentry);
 
 	/* Update app name to current GUC setting */
@@ -2805,6 +2807,7 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
 			/* st_xact_start_timestamp and st_waiting are also disabled */
 			beentry->st_xact_start_timestamp = 0;
 			beentry->st_waiting = false;
+			beentry->percent_complete = 0;
 			pgstat_increment_changecount_after(beentry);
 		}
 		return;
@@ -2837,7 +2840,33 @@ pgstat_report_activity(BackendState state, const char *cmd_str)
 		beentry->st_activity_start_timestamp = start_timestamp;
 	}
 
+	beentry->percent_complete = 0;
+	pgstat_increment_changecount_after(beentry);
+}
+
+/* ---------------------------------------------
+ *  Called after every fixed interval from vacuum's scan of the relation
+ *  in order to calculate and store vacuum progress.
+ * ---------------------------------------------
+ */
+
+void
+pgstat_report_progress(BlockNumber total_pages, BlockNumber scanned_pages)
+{
+	volatile PgBackendStatus *beentry = MyBEEntry;
+
+	if (!beentry)
+		return;
+
+	if (!pgstat_track_activities)
+		return;
+
+	pgstat_increment_changecount_before(beentry);
+	beentry->percent_complete = scanned_pages * 100 / total_pages;
 	pgstat_increment_changecount_after(beentry);
+
+	elog(LOG,"%d scanned_pages %d total pages\n", scanned_pages, total_pages);
+	elog(LOG,"%d percent_complete", beentry->percent_complete);
 }
 
 /* ----------
@@ -2994,6 +3023,8 @@ pgstat_read_current_status(void)
 				strcpy(localactivity, (char *) beentry->st_activity);
 				localentry->backendStatus.st_activity = localactivity;
 				localentry->backendStatus.st_ssl = beentry->st_ssl;
+				localentry->backendStatus.percent_complete = beentry->percent_complete;
+
 #ifdef USE_SSL
 				if (beentry->st_ssl)
 				{
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index f7c9bf6..7a05fd1 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -530,7 +530,7 @@ pg_stat_get_backend_idset(PG_FUNCTION_ARGS)
 Datum
 pg_stat_get_activity(PG_FUNCTION_ARGS)
 {
-#define PG_STAT_GET_ACTIVITY_COLS	22
+#define PG_STAT_GET_ACTIVITY_COLS	23
 	int			num_backends = pgstat_fetch_stat_numbackends();
 	int			curr_backend;
 	int			pid = PG_ARGISNULL(0) ? -1 : PG_GETARG_INT32(0);
@@ -777,6 +777,11 @@ pg_stat_get_activity(PG_FUNCTION_ARGS)
 			nulls[13] = true;
 		}
 
+		if (beentry->percent_complete != 0)
+			values[22] = Int32GetDatum(beentry->percent_complete);
+		else
+			nulls[22] = true;
+
 		tuplestore_putvalues(tupstore, tupdesc, values, nulls);
 
 		/* If only a single backend was requested, and we found it, break. */
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 1bed525..fc86289 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -2309,7 +2309,15 @@ static struct config_int ConfigureNamesInt[] =
 		-1, -1, INT_MAX,
 		NULL, NULL, NULL
 	},
-
+	{
+		{"track_activity_progress", PGC_SUSET, STATS_COLLECTOR,
+			gettext_noop("Collects progress information of executing commands."),
+			GUC_UNIT_MS
+		},
+		&pgstat_track_progress,
+		-1, -1, INT_MAX,
+		NULL, NULL, NULL
+	},
 	{
 		{"log_autovacuum_min_duration", PGC_SIGHUP, LOGGING_WHAT,
 			gettext_noop("Sets the minimum execution time above which "
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 6fd1278..9c75bec 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -2777,7 +2777,7 @@ DATA(insert OID = 3057 ( pg_stat_get_autoanalyze_count PGNSP PGUID 12 1 0 0 0 f
 DESCR("statistics: number of auto analyzes for a table");
 DATA(insert OID = 1936 (  pg_stat_get_backend_idset		PGNSP PGUID 12 1 100 0 0 f f f f t t s 0 0 23 "" _null_ _null_ _null_ _null_ _null_ pg_stat_get_backend_idset _null_ _null_ _null_ ));
 DESCR("statistics: currently active backend IDs");
-DATA(insert OID = 2022 (  pg_stat_get_activity			PGNSP PGUID 12 1 100 0 0 f f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,1184,869,25,23,28,28,16,25,25,23,16,25}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,ssl,sslversion,sslcipher,sslbits,sslcompression,sslclientdn}" _null_ _null_ pg_stat_get_activity _null_ _null_ _null_ ));
+DATA(insert OID = 2022 (  pg_stat_get_activity			PGNSP PGUID 12 1 100 0 0 f f f f f t s 1 0 2249 "23" "{23,26,23,26,25,25,25,16,1184,1184,1184,1184,869,25,23,28,28,16,25,25,23,16,25,23}" "{i,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o,o}" "{pid,datid,pid,usesysid,application_name,state,query,waiting,xact_start,query_start,backend_start,state_change,client_addr,client_hostname,client_port,backend_xid,backend_xmin,ssl,sslversion,sslcipher,sslbits,sslcompression,sslclientdn,percent_complete}" _null_ _null_ pg_stat_get_activity _null_ _null_ _null_ ));
 DESCR("statistics: information about currently active backends");
 DATA(insert OID = 3099 (  pg_stat_get_wal_senders	PGNSP PGUID 12 1 10 0 0 f f f f f t s 0 0 2249 "" "{23,25,3220,3220,3220,3220,23,25}" "{o,o,o,o,o,o,o,o}" "{pid,state,sent_location,write_location,flush_location,replay_location,sync_priority,sync_state}" _null_ _null_ pg_stat_get_wal_senders _null_ _null_ _null_ ));
 DESCR("statistics: information about currently active replication");
diff --git a/src/include/commands/vacuum.h b/src/include/commands/vacuum.h
index e3a31af..e5f1ac9 100644
--- a/src/include/commands/vacuum.h
+++ b/src/include/commands/vacuum.h
@@ -155,7 +155,6 @@ extern int	vacuum_freeze_table_age;
 extern int	vacuum_multixact_freeze_min_age;
 extern int	vacuum_multixact_freeze_table_age;
 
-
 /* in commands/vacuum.c */
 extern void ExecVacuum(VacuumStmt *vacstmt, bool isTopLevel);
 extern void vacuum(int options, RangeVar *relation, Oid relid,
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 9ecc163..704584b 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -20,6 +20,7 @@
 #include "utils/hsearch.h"
 #include "utils/relcache.h"
 
+#include "storage/block.h"
 
 /* ----------
  * Paths for the statistics files (relative to installation's $PGDATA).
@@ -776,6 +777,9 @@ typedef struct PgBackendStatus
 
 	/* current command string; MUST be null-terminated */
 	char	   *st_activity;
+
+	int		percent_complete;
+
 } PgBackendStatus;
 
 /*
@@ -871,6 +875,7 @@ extern PGDLLIMPORT int pgstat_track_activity_query_size;
 extern char *pgstat_stat_directory;
 extern char *pgstat_stat_tmpname;
 extern char *pgstat_stat_filename;
+extern int  pgstat_track_progress;
 
 /*
  * BgWriter statistics counters are updated directly by bgwriter and bufmgr
@@ -928,6 +933,7 @@ extern void pgstat_initialize(void);
 extern void pgstat_bestart(void);
 
 extern void pgstat_report_activity(BackendState state, const char *cmd_str);
+extern void pgstat_report_progress(BlockNumber total_pages, BlockNumber scanned_pages);
 extern void pgstat_report_tempfile(size_t filesize);
 extern void pgstat_report_appname(const char *appname);
 extern void pgstat_report_xact_timestamp(TimestampTz tstamp);
