diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 1a4c27b91c3d4ba54ad340867503c6e6d93f66c2..a4200b5549b259f3e4c503b63bdbf4b4d3af6e55 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -612,10 +612,13 @@ do_analyze_rel(Relation onerel, VacuumStmt *vacstmt,
 	/*
 	 * Report ANALYZE to the stats collector, too.  However, if doing
 	 * inherited stats we shouldn't report, because the stats collector only
-	 * tracks per-table stats.
+	 * tracks per-table stats.  Reset the changes_since_analyze counter only
+	 * if we analyzed all columns; otherwise, there is still work for
+	 * auto-analyze to do.
 	 */
 	if (!inh)
-		pgstat_report_analyze(onerel, totalrows, totaldeadrows);
+		pgstat_report_analyze(onerel, totalrows, totaldeadrows,
+							  (vacstmt->va_cols == NIL));
 
 	/* If this isn't part of VACUUM ANALYZE, let index AMs do cleanup */
 	if (!(vacstmt->options & VACOPT_VACUUM))
diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c
index 6725a0e043104fc9576d6e92fbabab68ad2ef8ec..ef865174ecb8fa955b8d1d4d12bf1c747c40d8d4 100644
--- a/src/backend/postmaster/pgstat.c
+++ b/src/backend/postmaster/pgstat.c
@@ -1275,11 +1275,15 @@ pgstat_report_vacuum(Oid tableoid, bool shared, PgStat_Counter tuples)
  * pgstat_report_analyze() -
  *
  *	Tell the collector about the table we just analyzed.
+ *
+ * Caller must provide new live- and dead-tuples estimates, as well as a
+ * flag indicating whether to reset the changes_since_analyze counter.
  * --------
  */
 void
 pgstat_report_analyze(Relation rel,
-					  PgStat_Counter livetuples, PgStat_Counter deadtuples)
+					  PgStat_Counter livetuples, PgStat_Counter deadtuples,
+					  bool resetcounter)
 {
 	PgStat_MsgAnalyze msg;
 
@@ -1316,6 +1320,7 @@ pgstat_report_analyze(Relation rel,
 	msg.m_databaseid = rel->rd_rel->relisshared ? InvalidOid : MyDatabaseId;
 	msg.m_tableoid = RelationGetRelid(rel);
 	msg.m_autovacuum = IsAutoVacuumWorkerProcess();
+	msg.m_resetcounter = resetcounter;
 	msg.m_analyzetime = GetCurrentTimestamp();
 	msg.m_live_tuples = livetuples;
 	msg.m_dead_tuples = deadtuples;
@@ -4419,10 +4424,12 @@ pgstat_recv_analyze(PgStat_MsgAnalyze *msg, int len)
 	tabentry->n_dead_tuples = msg->m_dead_tuples;
 
 	/*
-	 * We reset changes_since_analyze to zero, forgetting any changes that
-	 * occurred while the ANALYZE was in progress.
+	 * If commanded, reset changes_since_analyze to zero.  This forgets any
+	 * changes that were committed while the ANALYZE was in progress, but we
+	 * have no good way to estimate how many of those there were.
 	 */
-	tabentry->changes_since_analyze = 0;
+	if (msg->m_resetcounter)
+		tabentry->changes_since_analyze = 0;
 
 	if (msg->m_autovacuum)
 	{
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index a9edf8f66311922acb327c6eaa76feda01e72e7b..f6e7d9fb9ec8b29a9d6b0adcc031690e7e00d24d 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -344,6 +344,7 @@ typedef struct PgStat_MsgAnalyze
 	Oid			m_databaseid;
 	Oid			m_tableoid;
 	bool		m_autovacuum;
+	bool		m_resetcounter;
 	TimestampTz m_analyzetime;
 	PgStat_Counter m_live_tuples;
 	PgStat_Counter m_dead_tuples;
@@ -771,7 +772,8 @@ extern void pgstat_report_autovac(Oid dboid);
 extern void pgstat_report_vacuum(Oid tableoid, bool shared,
 					 PgStat_Counter tuples);
 extern void pgstat_report_analyze(Relation rel,
-					  PgStat_Counter livetuples, PgStat_Counter deadtuples);
+					  PgStat_Counter livetuples, PgStat_Counter deadtuples,
+					  bool resetcounter);
 
 extern void pgstat_report_recovery_conflict(int reason);
 extern void pgstat_report_deadlock(void);