*** a/src/backend/executor/nodeAgg.c
--- b/src/backend/executor/nodeAgg.c
***************
*** 665,673 **** build_hash_table(AggState *aggstate)
  	Agg		   *node = (Agg *) aggstate->ss.ps.plan;
  	MemoryContext tmpmem = aggstate->tmpcontext->ecxt_per_tuple_memory;
  	Size		entrysize;
- 	Bitmapset  *colnos;
- 	List	   *collist;
- 	int			i;
  
  	Assert(node->aggstrategy == AGG_HASHED);
  	Assert(node->numGroups > 0);
--- 665,670 ----
***************
*** 700,705 **** build_hash_table(AggState *aggstate)
--- 697,705 ----
  	 * then convert it to an integer list (cheaper to scan at runtime). The
  	 * list is in decreasing order so that the first entry is the largest;
  	 * lookup_hash_entry depends on this to use slot_getsomeattrs correctly.
+ 	 * Since build_hash_table() is invoked for every re-scan but we allocate
+ 	 * the column list in the per-query context, we need only do this the
+ 	 * first time through.
  	 *
  	 * Note: at present, searching the tlist/qual is not really necessary
  	 * since the parser should disallow any unaggregated references to
***************
*** 707,723 **** build_hash_table(AggState *aggstate)
  	 * support for SQL99 semantics that allow use of "functionally dependent"
  	 * columns that haven't been explicitly grouped by.
  	 */
  
! 	/* Find Vars that will be needed in tlist and qual */
! 	colnos = find_unaggregated_cols(aggstate);
! 	/* Add in all the grouping columns */
! 	for (i = 0; i < node->numCols; i++)
! 		colnos = bms_add_member(colnos, node->grpColIdx[i]);
! 	/* Convert to list, using lcons so largest element ends up first */
! 	collist = NIL;
! 	while ((i = bms_first_member(colnos)) >= 0)
! 		collist = lcons_int(i, collist);
! 	aggstate->hash_needed = collist;
  }
  
  /*
--- 707,730 ----
  	 * support for SQL99 semantics that allow use of "functionally dependent"
  	 * columns that haven't been explicitly grouped by.
  	 */
+ 	if (!aggstate->hash_needed)
+ 	{
+ 		Bitmapset  *colnos;
+ 		List	   *collist;
+ 		int			i;
  
! 		/* Find Vars that will be needed in tlist and qual */
! 		colnos = find_unaggregated_cols(aggstate);
! 		/* Add in all the grouping columns */
! 		for (i = 0; i < node->numCols; i++)
! 			colnos = bms_add_member(colnos, node->grpColIdx[i]);
! 		/* Convert to list, using lcons so largest element ends up first */
! 		collist = NIL;
! 		while ((i = bms_first_member(colnos)) >= 0)
! 			collist = lcons_int(i, collist);
! 		aggstate->hash_needed = collist;
! 		bms_free(colnos);
! 	}
  }
  
  /*
