diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index fa628cd8eef..bbadd58d893 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -349,25 +349,6 @@ typedef struct
 	List	   *already_used;	/* expressions already dealt with */
 } ec_member_foreign_arg;
 
-/* Pairs of remote columns with local columns */
-typedef struct
-{
-	AttrNumber	local_attnum;
-	char	   *local_attname;
-	char	   *remote_attname;
-	int			res_index;
-} RemoteAttributeMapping;
-
-/* Result sets that are returned from a foreign statistics scan */
-typedef struct
-{
-	PGresult   *rel;
-	PGresult   *att;
-	double		livetuples;
-	double		deadtuples;
-	int			version;
-} RemoteStatsResults;
-
 /* Column order in relation stats query */
 enum RelStatsColumns
 {
@@ -397,6 +378,25 @@ enum AttStatsColumns
 	ATTSTATS_NUM_FIELDS,
 };
 
+/* Result sets that are returned from a foreign statistics scan */
+typedef struct
+{
+	PGresult   *rel;			/* result for relation stats query */
+	PGresult   *att;			/* result for attribute stats query */
+	double		livetuples;		/* livetuples estimates, for pgstat report */
+	double		deadtuples;		/* deadtuples estimates, for pgstat report */
+	int			version;		/* version of remote server */
+} RemoteStatsResults;
+
+/* Pairs of remote columns with local columns */
+typedef struct
+{
+	AttrNumber	local_attnum;	/* attribute number of local column */
+	char	   *local_attname;	/* attribute name of local column */
+	char	   *remote_attname; /* attribute name of remote column */
+	int			res_index;		/* index of row in attribute stats result */
+} RemoteAttributeMapping;
+
 /*
  * SQL functions
  */
@@ -592,12 +592,12 @@ static void analyze_row_processor(PGresult *res, int row,
 								  PgFdwAnalyzeState *astate);
 static bool fetch_remote_statistics(Relation relation,
 									List *va_cols,
-									ForeignTable *table,
 									const char *local_schemaname,
 									const char *local_relname,
-									int *p_attrcnt,
+									ForeignTable *table,
+									RemoteStatsResults *remstats,
 									RemoteAttributeMapping **p_remattrmap,
-									RemoteStatsResults *remstats);
+									int *p_attrcnt);
 static PGresult *fetch_relstats(PGconn *conn, Relation relation);
 static PGresult *fetch_attstats(PGconn *conn, int server_version_num,
 								const char *remote_schemaname, const char *remote_relname,
@@ -612,14 +612,14 @@ static bool match_attrmap(PGresult *res,
 						  const char *local_relname,
 						  const char *remote_schemaname,
 						  const char *remote_relname,
-						  int attrcnt,
-						  RemoteAttributeMapping *remattrmap);
+						  RemoteAttributeMapping *remattrmap,
+						  int attrcnt);
 static bool import_fetched_statistics(Relation relation,
 									  const char *schemaname,
 									  const char *relname,
-									  int attrcnt,
+									  RemoteStatsResults *remstats,
 									  const RemoteAttributeMapping *remattrmap,
-									  RemoteStatsResults *remstats);
+									  int attrcnt);
 static char *get_opt_value(PGresult *res, int row, int col);
 static void set_text_arg(NullableDatum *arg, const char *s);
 static void set_int32_arg(NullableDatum *arg, const char *s);
@@ -5763,12 +5763,12 @@ postgresImportForeignStatistics(Relation relation, List *va_cols, int elevel)
 	starttime = GetCurrentTimestamp();
 
 	ok = fetch_remote_statistics(relation, va_cols,
-								 table, schemaname, relname,
-								 &attrcnt, &remattrmap, &remstats);
+								 schemaname, relname, table,
+								 &remstats, &remattrmap, &attrcnt);
 
 	if (ok)
 		ok = import_fetched_statistics(relation, schemaname, relname,
-									   attrcnt, remattrmap, &remstats);
+									   &remstats, remattrmap, attrcnt);
 
 	if (ok)
 	{
@@ -5794,12 +5794,12 @@ postgresImportForeignStatistics(Relation relation, List *va_cols, int elevel)
 static bool
 fetch_remote_statistics(Relation relation,
 						List *va_cols,
-						ForeignTable *table,
 						const char *local_schemaname,
 						const char *local_relname,
-						int *p_attrcnt,
+						ForeignTable *table,
+						RemoteStatsResults *remstats,
 						RemoteAttributeMapping **p_remattrmap,
-						RemoteStatsResults *remstats)
+						int *p_attrcnt)
 {
 	const char *remote_schemaname = NULL;
 	const char *remote_relname = NULL;
@@ -5816,7 +5816,7 @@ fetch_remote_statistics(Relation relation,
 	ListCell   *lc;
 
 	/*
-	 * Assume the remote schema/relation names are the same as the local name
+	 * Assume the remote schema/table names are the same as the local name
 	 * unless the foreign table's options tell us otherwise.
 	 */
 	remote_schemaname = local_schemaname;
@@ -5834,6 +5834,9 @@ fetch_remote_statistics(Relation relation,
 	/*
 	 * Get connection to the foreign server.  Connection manager will
 	 * establish new connection if necessary.
+	 *
+	 * Note that unlike the sampling case, we only query pg_class and
+	 * pg_stats, so we do the remote access as the current user.
 	 */
 	user = GetUserMapping(GetUserId(), table->serverid);
 	conn = GetConnection(user, false, NULL);
@@ -5870,36 +5873,26 @@ fetch_remote_statistics(Relation relation,
 	 * If the reltuples value > 0, then we can expect to find attribute stats
 	 * for the remote table.
 	 *
-	 * In v14 or later, if a reltuples value is -1, it means the table has
-	 * never been analyzed, so we wouldn't expect to find the stats for the
-	 * table; fallback to sampling in that case.  If the value is 0, it means
-	 * it was empty; in which case skip the stats and import relation stats
-	 * only.
+	 * In v14 or later, if the value is -1, it means the table had never been
+	 * analyzed, so we wouldn't expect to find the stats; fallback to sampling
+	 * in that case.  If the value is 0, it means it was empty, in which case
+	 * we don't need the stats, so import relation stats only.
 	 *
 	 * In versions prior to v14, a value of 0 was ambiguous; it could mean
-	 * that the table had never been analyzed, or that it was empty.  Either
-	 * way, we wouldn't expect to find the stats for the table, so we fallback
-	 * to sampling.
+	 * that the table had never been analyzed, or that it was empty.  Assuming
+	 * the former, fallback to sampling.
 	 */
 	reltuples = strtod(PQgetvalue(relstats, 0, RELSTATS_RELTUPLES), NULL);
-	if (((server_version_num < 140000) && (reltuples == 0)) ||
-		((server_version_num >= 140000) && (reltuples == -1)))
-	{
-		ereport(WARNING,
-				errmsg("could not import statistics for foreign table \"%s.%s\" --- remote table \"%s.%s\" has no relation statistics to import",
-					   local_schemaname, local_relname,
-					   remote_schemaname, remote_relname));
-		goto fetch_cleanup;
-	}
-
 	if (reltuples > 0)
 	{
 		StringInfoData column_list;
 
+		/* Create mappings of local/remote columns. */
 		*p_remattrmap = remattrmap = build_remattrmap(relation, va_cols,
 													  &attrcnt, &column_list);
 		*p_attrcnt = attrcnt;
 
+		/* Try to get attribute stats if needed. */
 		if (attrcnt > 0)
 		{
 			/* Fetch attribute stats. */
@@ -5913,10 +5906,19 @@ fetch_remote_statistics(Relation relation,
 			if (!match_attrmap(attstats,
 							   local_schemaname, local_relname,
 							   remote_schemaname, remote_relname,
-							   attrcnt, remattrmap))
+							   remattrmap, attrcnt))
 				goto fetch_cleanup;
 		}
 	}
+	else if (((server_version_num < 140000) && (reltuples == 0)) ||
+			 ((server_version_num >= 140000) && (reltuples == -1)))
+	{
+		ereport(WARNING,
+				errmsg("could not import statistics for foreign table \"%s.%s\" --- remote table \"%s.%s\" has no relation statistics to import",
+					   local_schemaname, local_relname,
+					   remote_schemaname, remote_relname));
+		goto fetch_cleanup;
+	}
 
 	/* We assume that we have no dead tuple. */
 	remstats->deadtuples = 0.0;
@@ -6042,7 +6044,7 @@ build_remattrmap(Relation relation, List *va_cols,
 		Form_pg_attribute attr = TupleDescAttr(tupdesc, i);
 		char	   *attname = NameStr(attr->attname);
 		AttrNumber	attnum = attr->attnum;
-		char	   *remote_attname;
+		char	   *colname;
 		List	   *fc_options;
 		ListCell   *lc;
 
@@ -6054,7 +6056,7 @@ build_remattrmap(Relation relation, List *va_cols,
 			continue;
 
 		/* If the column_name option is not specified, go with attname. */
-		remote_attname = attname;
+		colname = attname;
 		fc_options = GetForeignColumnOptions(RelationGetRelid(relation), attnum);
 		foreach(lc, fc_options)
 		{
@@ -6062,24 +6064,24 @@ build_remattrmap(Relation relation, List *va_cols,
 
 			if (strcmp(def->defname, "column_name") == 0)
 			{
-				remote_attname = defGetString(def);
+				colname = defGetString(def);
 				break;
 			}
 		}
 
 		if (attrcnt > 0)
 			appendStringInfoString(column_list, ", ");
-		deparseStringLiteral(column_list, remote_attname);
+		deparseStringLiteral(column_list, colname);
 
 		remattrmap[attrcnt].local_attnum = attnum;
 		remattrmap[attrcnt].local_attname = pstrdup(attname);
-		remattrmap[attrcnt].remote_attname = pstrdup(remote_attname);
+		remattrmap[attrcnt].remote_attname = pstrdup(colname);
 		remattrmap[attrcnt].res_index = -1;
 		attrcnt++;
 	}
 	appendStringInfoChar(column_list, ']');
 
-	/* Sort mappings by remote attribute name if needed. */
+	/* Sort the mappings by remote_attname if needed. */
 	if (attrcnt > 1)
 		qsort(remattrmap, attrcnt, sizeof(RemoteAttributeMapping), remattrmap_cmp);
 
@@ -6158,8 +6160,8 @@ match_attrmap(PGresult *res,
 			  const char *local_relname,
 			  const char *remote_schemaname,
 			  const char *remote_relname,
-			  int attrcnt,
-			  RemoteAttributeMapping *remattrmap)
+			  RemoteAttributeMapping *remattrmap,
+			  int attrcnt)
 {
 	int			numrows = PQntuples(res);
 	int			row = -1;
@@ -6246,9 +6248,9 @@ static bool
 import_fetched_statistics(Relation relation,
 						  const char *schemaname,
 						  const char *relname,
-						  int attrcnt,
+						  RemoteStatsResults *remstats,
 						  const RemoteAttributeMapping *remattrmap,
-						  RemoteStatsResults *remstats)
+						  int attrcnt)
 {
 	PGresult   *res;
 	NullableDatum args[ATTSTATS_NUM_FIELDS];
@@ -6340,6 +6342,7 @@ import_fetched_statistics(Relation relation,
 	Assert(!args[1].isnull);
 	set_float_arg(&args[2], get_opt_value(res, 0, RELSTATS_RELTUPLES));
 	Assert(!args[2].isnull);
+	/* We don't import relallvisible/relallfrozen. */
 	args[3].value = (Datum) 0;
 	args[3].isnull = true;
 	args[4].value = (Datum) 0;
diff --git a/doc/src/sgml/fdwhandler.sgml b/doc/src/sgml/fdwhandler.sgml
index 0103fdacfdf..502441fefcb 100644
--- a/doc/src/sgml/fdwhandler.sgml
+++ b/doc/src/sgml/fdwhandler.sgml
@@ -1430,7 +1430,7 @@ ImportForeignStatistics(Relation relation,
      If the function imports the statistics successfully, it should return
      <literal>true</literal>.  Otherwise, return <literal>false</literal>, in
      which case <function>AnalyzeForeignTable</function> callback function is
-     called on the foreign table to collect statistics locally, if supported.
+     called on the foreign table to generate statistics locally, if supported.
     </para>
 
     <para>
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 15beb8150de..c05f9f50e43 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -1171,6 +1171,11 @@ examine_attribute(Relation onerel, int attnum, Node *index_expr)
 	return stats;
 }
 
+/*
+ * Determine whether the column is analyzable.
+ *
+ * If the column is analyzable, return its attstattarget value, if asked to.
+ */
 bool
 attribute_is_analyzable(Relation onerel, int attnum, Form_pg_attribute attr,
 						int *p_attstattarget)
