diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 23ef23c13e..113ddf1f5b 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -331,12 +331,14 @@ static autovac_table *table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 static void recheck_relation_needs_vacanalyze(Oid relid, AutoVacOpts *avopts,
 											  Form_pg_class classForm,
 											  int effective_multixact_freeze_max_age,
-											  bool *dovacuum, bool *doanalyze, bool *wraparound);
+											  bool *dovacuum, bool *doanalyze, bool *wraparound,
+											  bool *skip_index_cleanup);
 static void relation_needs_vacanalyze(Oid relid, AutoVacOpts *relopts,
 									  Form_pg_class classForm,
 									  PgStat_StatTabEntry *tabentry,
 									  int effective_multixact_freeze_max_age,
-									  bool *dovacuum, bool *doanalyze, bool *wraparound);
+									  bool *dovacuum, bool *doanalyze, bool *wraparound,
+									  bool *skip_index_cleanup);
 
 static void autovacuum_do_vac_analyze(autovac_table *tab,
 									  BufferAccessStrategy bstrategy);
@@ -2080,6 +2082,7 @@ do_autovacuum(void)
 		bool		dovacuum;
 		bool		doanalyze;
 		bool		wraparound;
+		bool		skip_index_cleanup;
 
 		if (classForm->relkind != RELKIND_RELATION &&
 			classForm->relkind != RELKIND_MATVIEW)
@@ -2120,7 +2123,8 @@ do_autovacuum(void)
 		/* Check if it needs vacuum or analyze */
 		relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
 								  effective_multixact_freeze_max_age,
-								  &dovacuum, &doanalyze, &wraparound);
+								  &dovacuum, &doanalyze, &wraparound,
+								  &skip_index_cleanup);
 
 		/* Relations that need work are added to table_oids */
 		if (dovacuum || doanalyze)
@@ -2173,6 +2177,7 @@ do_autovacuum(void)
 		bool		dovacuum;
 		bool		doanalyze;
 		bool		wraparound;
+		bool		skip_index_cleanup;
 
 		/*
 		 * We cannot safely process other backends' temp tables, so skip 'em.
@@ -2203,7 +2208,8 @@ do_autovacuum(void)
 
 		relation_needs_vacanalyze(relid, relopts, classForm, tabentry,
 								  effective_multixact_freeze_max_age,
-								  &dovacuum, &doanalyze, &wraparound);
+								  &dovacuum, &doanalyze, &wraparound,
+								  &skip_index_cleanup);
 
 		/* ignore analyze for toast tables */
 		if (dovacuum)
@@ -2801,6 +2807,7 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	bool		doanalyze;
 	autovac_table *tab = NULL;
 	bool		wraparound;
+	bool		skip_index_cleanup;
 	AutoVacOpts *avopts;
 	static bool reuse_stats = false;
 
@@ -2842,7 +2849,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 	{
 		recheck_relation_needs_vacanalyze(relid, avopts, classForm,
 										  effective_multixact_freeze_max_age,
-										  &dovacuum, &doanalyze, &wraparound);
+										  &dovacuum, &doanalyze, &wraparound,
+										  &skip_index_cleanup);
 
 		/* Quick exit if a relation doesn't need to be vacuumed or analyzed */
 		if (!doanalyze && !dovacuum)
@@ -2857,7 +2865,8 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 
 	recheck_relation_needs_vacanalyze(relid, avopts, classForm,
 									  effective_multixact_freeze_max_age,
-									  &dovacuum, &doanalyze, &wraparound);
+									  &dovacuum, &doanalyze, &wraparound,
+									  &skip_index_cleanup);
 
 	/* OK, it needs something done */
 	if (doanalyze || dovacuum)
@@ -2923,7 +2932,9 @@ table_recheck_autovac(Oid relid, HTAB *table_toast_map,
 		tab->at_params.options = (dovacuum ? VACOPT_VACUUM : 0) |
 			(doanalyze ? VACOPT_ANALYZE : 0) |
 			(!wraparound ? VACOPT_SKIP_LOCKED : 0);
-		tab->at_params.index_cleanup = VACOPT_TERNARY_DEFAULT;
+		tab->at_params.index_cleanup = (skip_index_cleanup
+										? VACOPT_TERNARY_DISABLED
+										: VACOPT_TERNARY_DEFAULT);
 		tab->at_params.truncate = VACOPT_TERNARY_DEFAULT;
 		/* As of now, we don't support parallel vacuum for autovacuum */
 		tab->at_params.nworkers = -1;
@@ -2982,7 +2993,8 @@ recheck_relation_needs_vacanalyze(Oid relid,
 								  int effective_multixact_freeze_max_age,
 								  bool *dovacuum,
 								  bool *doanalyze,
-								  bool *wraparound)
+								  bool *wraparound,
+								  bool *skip_index_cleanup)
 {
 	PgStat_StatTabEntry *tabentry;
 	PgStat_StatDBEntry *shared = NULL;
@@ -2999,7 +3011,8 @@ recheck_relation_needs_vacanalyze(Oid relid,
 
 	relation_needs_vacanalyze(relid, avopts, classForm, tabentry,
 							  effective_multixact_freeze_max_age,
-							  dovacuum, doanalyze, wraparound);
+							  dovacuum, doanalyze, wraparound,
+							  skip_index_cleanup);
 
 	/* ignore ANALYZE for toast tables */
 	if (classForm->relkind == RELKIND_TOASTVALUE)
@@ -3011,7 +3024,8 @@ recheck_relation_needs_vacanalyze(Oid relid,
  *
  * Check whether a relation needs to be vacuumed or analyzed; return each into
  * "dovacuum" and "doanalyze", respectively.  Also return whether the vacuum is
- * being forced because of Xid or multixact wraparound.
+ * being forced because of Xid or multixact wraparound and whether or not to skip
+ * index vacuuming.
  *
  * relopts is a pointer to the AutoVacOpts options (either for itself in the
  * case of a plain table, or for either itself or its parent table in the case
@@ -3052,7 +3066,8 @@ relation_needs_vacanalyze(Oid relid,
  /* output params below */
 						  bool *dovacuum,
 						  bool *doanalyze,
-						  bool *wraparound)
+						  bool *wraparound,
+						  bool *skip_index_cleanup)
 {
 	bool		force_vacuum;
 	bool		av_enabled;
@@ -3207,6 +3222,40 @@ relation_needs_vacanalyze(Oid relid,
 	/* ANALYZE refuses to work with pg_statistic */
 	if (relid == StatisticRelationId)
 		*doanalyze = false;
+
+	/*
+	 * If a table is at risk of wraparound, we further check if the table's
+	 * relfrozenxid is too older than autovacuum_freeze_max_age (more than
+	 * autovacuum_freeze_max_age * 1.5 XIDs old).  If so, we skip index vacuuming
+	 * to quickly complete vacuum operation and advance relfrozenxid.
+	 */
+	if (force_vacuum)
+	{
+		TransactionId	xidSkipIndCleanupLimit;
+		MultiXactId		multiSkipIndCleanupLimit;
+
+		freeze_max_age = Min(freeze_max_age * 1.5, MAX_AUTOVACUUM_FREEZE_MAX_AGE);
+		xidSkipIndCleanupLimit = recentXid - freeze_max_age;
+		if (xidSkipIndCleanupLimit < FirstNormalTransactionId)
+			xidSkipIndCleanupLimit -= FirstNormalTransactionId;
+
+		*skip_index_cleanup = (TransactionIdIsNormal(classForm->relfrozenxid) &&
+							  TransactionIdPrecedes(classForm->relfrozenxid,
+													xidSkipIndCleanupLimit));
+
+		if (!(*skip_index_cleanup))
+		{
+			multixact_freeze_max_age = Min(multixact_freeze_max_age * 1.5,
+										   MAX_AUTOVACUUM_FREEZE_MAX_AGE);
+			multiSkipIndCleanupLimit = recentMulti - multixact_freeze_max_age;
+			if (multiSkipIndCleanupLimit < FirstMultiXactId)
+				multiSkipIndCleanupLimit -= FirstMultiXactId;
+
+			*skip_index_cleanup = (MultiXactIdIsValid(classForm->relminmxid) &&
+								   MultiXactIdPrecedes(classForm->relminmxid,
+													   multiSkipIndCleanupLimit));
+		}
+	}
 }
 
 /*
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 855076b1fd..26ba3fdbbe 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -3197,7 +3197,7 @@ static struct config_int ConfigureNamesInt[] =
 		},
 		&autovacuum_freeze_max_age,
 		/* see pg_resetwal if you change the upper-limit value */
-		200000000, 100000, 2000000000,
+		200000000, 100000, MAX_AUTOVACUUM_FREEZE_MAX_AGE,
 		NULL, NULL, NULL
 	},
 	{
@@ -3207,7 +3207,7 @@ static struct config_int ConfigureNamesInt[] =
 			NULL
 		},
 		&autovacuum_multixact_freeze_max_age,
-		400000000, 10000, 2000000000,
+		400000000, 10000, MAX_AUTOVACUUM_FREEZE_MAX_AGE,
 		NULL, NULL, NULL
 	},
 	{
diff --git a/src/include/postmaster/autovacuum.h b/src/include/postmaster/autovacuum.h
index aacdd0f575..e56e0d73ad 100644
--- a/src/include/postmaster/autovacuum.h
+++ b/src/include/postmaster/autovacuum.h
@@ -16,6 +16,12 @@
 
 #include "storage/block.h"
 
+/*
+ * Maximum value of autovacuum_freeze_max_age and
+ * autovacuum_multixact_freeze_max_age parameters.
+ */
+#define MAX_AUTOVACUUM_FREEZE_MAX_AGE	2000000000
+
 /*
  * Other processes can request specific work from autovacuum, identified by
  * AutoVacuumWorkItem elements.
