*** a/src/backend/postmaster/autovacuum.c
--- b/src/backend/postmaster/autovacuum.c
***************
*** 1890,1895 **** get_database_list(void)
--- 1890,1919 ----
  	return dblist;
  }
  
+ typedef struct vacuum_table
+ {
+ 	Oid		reloid;
+ 	bool	wraparound;
+ } vacuum_table;
+ 
+ /*
+  * qsort comparator.  Tables marked for wraparound sort first.
+  */
+ static int
+ vacpriority_comparator(const void *a, const void *b)
+ {
+ 	const vacuum_table *taba = *(vacuum_table *const *) a;
+ 	const vacuum_table *tabb = *(vacuum_table *const *) b;
+ 
+ 	if (taba->wraparound == tabb->wraparound)
+ 		return 0;
+ 
+ 	if (taba->wraparound)
+ 		return -1;
+ 	else
+ 		return 1;
+ }
+ 
  /*
   * Process a database table-by-table
   *
***************
*** 1903,1917 **** do_autovacuum(void)
  	HeapTuple	tuple;
  	HeapScanDesc relScan;
  	Form_pg_database dbForm;
- 	List	   *table_oids = NIL;
  	HASHCTL		ctl;
  	HTAB	   *table_toast_map;
- 	ListCell   *volatile cell;
  	PgStat_StatDBEntry *shared;
  	PgStat_StatDBEntry *dbentry;
  	BufferAccessStrategy bstrategy;
  	ScanKeyData key;
  	TupleDesc	pg_class_desc;
  
  	/*
  	 * StartTransactionCommand and CommitTransactionCommand will automatically
--- 1927,1943 ----
  	HeapTuple	tuple;
  	HeapScanDesc relScan;
  	Form_pg_database dbForm;
  	HASHCTL		ctl;
  	HTAB	   *table_toast_map;
  	PgStat_StatDBEntry *shared;
  	PgStat_StatDBEntry *dbentry;
  	BufferAccessStrategy bstrategy;
  	ScanKeyData key;
  	TupleDesc	pg_class_desc;
+ 	vacuum_table **tables;
+ 	int			ntables;
+ 	int			maxtables;
+ 	int			i;
  
  	/*
  	 * StartTransactionCommand and CommitTransactionCommand will automatically
***************
*** 1986,1991 **** do_autovacuum(void)
--- 2012,2022 ----
  								  &ctl,
  								  HASH_ELEM | HASH_FUNCTION);
  
+ 	/* initialize our tasklist */
+ 	ntables = 0;
+ 	maxtables = 32;
+ 	tables = palloc(maxtables * sizeof(vacuum_table *));
+ 
  	/*
  	 * Scan pg_class to determine which tables to vacuum.
  	 *
***************
*** 2077,2085 **** do_autovacuum(void)
  		}
  		else
  		{
! 			/* relations that need work are added to table_oids */
  			if (dovacuum || doanalyze)
! 				table_oids = lappend_oid(table_oids, relid);
  
  			/*
  			 * Remember the association for the second pass.  Note: we must do
--- 2108,2133 ----
  		}
  		else
  		{
! 			/* relations that need work are added to our tasklist */
  			if (dovacuum || doanalyze)
! 			{
! 				vacuum_table *tab;
! 
! 				/* enlarge the array if necessary */
! 				if (ntables >= maxtables)
! 				{
! 					maxtables *= 2;
! 					tables = repalloc(tables,
! 									  maxtables * sizeof(vacuum_table *));
! 				}
! 
! 				tab = palloc(sizeof(vacuum_table));
! 
! 				tab->reloid = relid;
! 				tab->wraparound = wraparound;
! 
! 				tables[ntables++] = tab;
! 			}
  
  			/*
  			 * Remember the association for the second pass.  Note: we must do
***************
*** 2162,2168 **** do_autovacuum(void)
  
  		/* ignore analyze for toast tables */
  		if (dovacuum)
! 			table_oids = lappend_oid(table_oids, relid);
  	}
  
  	heap_endscan(relScan);
--- 2210,2233 ----
  
  		/* ignore analyze for toast tables */
  		if (dovacuum)
! 		{
! 			vacuum_table *tab;
! 
! 			/* enlarge the array if necessary */
! 			if (ntables >= maxtables)
! 			{
! 				maxtables *= 2;
! 				tables = repalloc(tables,
! 								  maxtables * sizeof(vacuum_table *));
! 			}
! 
! 			tab = palloc(sizeof(vacuum_table));
! 
! 			tab->reloid = relid;
! 			tab->wraparound = wraparound;
! 
! 			tables[ntables++] = tab;
! 		}
  	}
  
  	heap_endscan(relScan);
***************
*** 2185,2196 **** do_autovacuum(void)
  										  ALLOCSET_DEFAULT_MINSIZE,
  										  ALLOCSET_DEFAULT_MAXSIZE);
  
  	/*
  	 * Perform operations on collected tables.
  	 */
! 	foreach(cell, table_oids)
  	{
- 		Oid			relid = lfirst_oid(cell);
  		autovac_table *tab;
  		bool		skipit;
  		int			stdVacuumCostDelay;
--- 2250,2264 ----
  										  ALLOCSET_DEFAULT_MINSIZE,
  										  ALLOCSET_DEFAULT_MAXSIZE);
  
+ 	/* sort our task list */
+ 	qsort(tables, ntables, sizeof(vacuum_table *),
+ 		  vacpriority_comparator);
+ 
  	/*
  	 * Perform operations on collected tables.
  	 */
! 	for (i = 0; i < ntables; i++)
  	{
  		autovac_table *tab;
  		bool		skipit;
  		int			stdVacuumCostDelay;
***************
*** 2224,2230 **** do_autovacuum(void)
  			if (worker->wi_dboid != MyDatabaseId)
  				continue;
  
! 			if (worker->wi_tableoid == relid)
  			{
  				skipit = true;
  				break;
--- 2292,2298 ----
  			if (worker->wi_dboid != MyDatabaseId)
  				continue;
  
! 			if (worker->wi_tableoid == tables[i]->reloid)
  			{
  				skipit = true;
  				break;
***************
*** 2248,2254 **** do_autovacuum(void)
  		 * the race condition is not closed but it is very small.
  		 */
  		MemoryContextSwitchTo(AutovacMemCxt);
! 		tab = table_recheck_autovac(relid, table_toast_map, pg_class_desc);
  		if (tab == NULL)
  		{
  			/* someone else vacuumed the table, or it went away */
--- 2316,2323 ----
  		 * the race condition is not closed but it is very small.
  		 */
  		MemoryContextSwitchTo(AutovacMemCxt);
! 		tab = table_recheck_autovac(tables[i]->reloid, table_toast_map,
! 									pg_class_desc);
  		if (tab == NULL)
  		{
  			/* someone else vacuumed the table, or it went away */
***************
*** 2260,2266 **** do_autovacuum(void)
  		 * Ok, good to go.	Store the table in shared memory before releasing
  		 * the lock so that other workers don't vacuum it concurrently.
  		 */
! 		MyWorkerInfo->wi_tableoid = relid;
  		LWLockRelease(AutovacuumScheduleLock);
  
  		/*
--- 2329,2335 ----
  		 * Ok, good to go.	Store the table in shared memory before releasing
  		 * the lock so that other workers don't vacuum it concurrently.
  		 */
! 		MyWorkerInfo->wi_tableoid = tables[i]->reloid;
  		LWLockRelease(AutovacuumScheduleLock);
  
  		/*
***************
*** 2361,2366 **** deleted:
--- 2430,2436 ----
  		if (tab->at_relname != NULL)
  			pfree(tab->at_relname);
  		pfree(tab);
+ 		pfree(tables[i]);
  
  		/*
  		 * Remove my info from shared memory.  We could, but intentionally
