diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 477b9f7fb8..7f76d0ab9d 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -1019,7 +1019,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 		childrel->reltarget->exprs = (List *)
 			adjust_appendrel_attrs(root,
 								   (Node *) rel->reltarget->exprs,
-								   1, &appinfo);
+								   bms_make_singleton(appinfo->child_relid));
 
 		/*
 		 * We have to make child entries in the EquivalenceClass data
@@ -1061,7 +1061,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 			Assert(IsA(rinfo, RestrictInfo));
 			childqual = adjust_appendrel_attrs(root,
 											   (Node *) rinfo->clause,
-											   1, &appinfo);
+											   bms_make_singleton(appinfo->child_relid));
 			childqual = eval_const_expressions(root, childqual);
 			/* check for flat-out constant */
 			if (childqual && IsA(childqual, Const))
@@ -1178,7 +1178,7 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
 		childrel->joininfo = (List *)
 			adjust_appendrel_attrs(root,
 								   (Node *) rel->joininfo,
-								   1, &appinfo);
+								   bms_make_singleton(appinfo->child_relid));
 
 		/*
 		 * If parallelism is allowable for this query in general, see whether
diff --git a/src/backend/optimizer/path/equivclass.c b/src/backend/optimizer/path/equivclass.c
index b22b36ec0e..2be3caa56f 100644
--- a/src/backend/optimizer/path/equivclass.c
+++ b/src/backend/optimizer/path/equivclass.c
@@ -2152,7 +2152,7 @@ add_child_rel_equivalences(PlannerInfo *root,
 				child_expr = (Expr *)
 					adjust_appendrel_attrs(root,
 										   (Node *) cur_em->em_expr,
-										   1, &appinfo);
+										   bms_make_singleton(appinfo->child_relid));
 
 				/*
 				 * Transform em_relids to match.  Note we do *not* do
diff --git a/src/backend/optimizer/path/joinrels.c b/src/backend/optimizer/path/joinrels.c
index 7008e1318e..ce1efd403e 100644
--- a/src/backend/optimizer/path/joinrels.c
+++ b/src/backend/optimizer/path/joinrels.c
@@ -1366,13 +1366,10 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 		List	   *child_restrictlist;
 		RelOptInfo *child_joinrel;
 		Relids		child_joinrelids;
-		AppendRelInfo **appinfos;
-		int			nappinfos;
 
 		/* We should never try to join two overlapping sets of rels. */
 		Assert(!bms_overlap(child_rel1->relids, child_rel2->relids));
 		child_joinrelids = bms_union(child_rel1->relids, child_rel2->relids);
-		appinfos = find_appinfos_by_relids(root, child_joinrelids, &nappinfos);
 
 		/*
 		 * Construct SpecialJoinInfo from parent join relations's
@@ -1389,8 +1386,7 @@ try_partitionwise_join(PlannerInfo *root, RelOptInfo *rel1, RelOptInfo *rel2,
 		child_restrictlist =
 			(List *) adjust_appendrel_attrs(root,
 											(Node *) parent_restrictlist,
-											nappinfos, appinfos);
-		pfree(appinfos);
+											child_joinrelids);
 
 		child_joinrel = joinrel->part_rels[cnt_parts];
 		if (!child_joinrel)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 67a2c7a581..a0b3123a2e 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -1163,6 +1163,7 @@ inheritance_planner(PlannerInfo *root)
 	List	   *final_rtable = NIL;
 	int			save_rel_array_size = 0;
 	RelOptInfo **save_rel_array = NULL;
+	AppendRelInfo **save_append_rel_array = NULL;
 	List	   *subpaths = NIL;
 	List	   *subroots = NIL;
 	List	   *resultRelations = NIL;
@@ -1311,7 +1312,7 @@ inheritance_planner(PlannerInfo *root)
 		subroot->parse = (Query *)
 			adjust_appendrel_attrs(parent_root,
 								   (Node *) parent_parse,
-								   1, &appinfo);
+								   bms_make_singleton(appinfo->child_relid));
 
 		/*
 		 * If there are securityQuals attached to the parent, move them to the
@@ -1529,6 +1530,7 @@ inheritance_planner(PlannerInfo *root)
 		}
 		save_rel_array_size = subroot->simple_rel_array_size;
 		save_rel_array = subroot->simple_rel_array;
+		save_append_rel_array = subroot->append_rel_array;
 
 		/* Make sure any initplans from this rel get into the outer list */
 		root->init_plans = subroot->init_plans;
@@ -1579,6 +1581,8 @@ inheritance_planner(PlannerInfo *root)
 	parse->rtable = final_rtable;
 	root->simple_rel_array_size = save_rel_array_size;
 	root->simple_rel_array = save_rel_array;
+	root->append_rel_array = save_append_rel_array;
+
 	/* Must reconstruct master's simple_rte_array, too */
 	root->simple_rte_array = (RangeTblEntry **)
 		palloc0((list_length(final_rtable) + 1) * sizeof(RangeTblEntry *));
@@ -6924,13 +6928,9 @@ apply_scanjoin_target_to_paths(PlannerInfo *root,
 		{
 			RelOptInfo *child_rel = rel->part_rels[partition_idx];
 			ListCell   *lc;
-			AppendRelInfo **appinfos;
-			int			nappinfos;
 			List	   *child_scanjoin_targets = NIL;
 
 			/* Translate scan/join targets for this child. */
-			appinfos = find_appinfos_by_relids(root, child_rel->relids,
-											   &nappinfos);
 			foreach(lc, scanjoin_targets)
 			{
 				PathTarget *target = lfirst_node(PathTarget, lc);
@@ -6939,11 +6939,10 @@ apply_scanjoin_target_to_paths(PlannerInfo *root,
 				target->exprs = (List *)
 					adjust_appendrel_attrs(root,
 										   (Node *) target->exprs,
-										   nappinfos, appinfos);
+										   child_rel->relids);
 				child_scanjoin_targets = lappend(child_scanjoin_targets,
 												 target);
 			}
-			pfree(appinfos);
 
 			/* Recursion does the real work. */
 			apply_scanjoin_target_to_paths(root, child_rel,
@@ -7022,8 +7021,6 @@ create_partitionwise_grouping_paths(PlannerInfo *root,
 	{
 		RelOptInfo *child_input_rel = input_rel->part_rels[cnt_parts];
 		PathTarget *child_target = copy_pathtarget(target);
-		AppendRelInfo **appinfos;
-		int			nappinfos;
 		GroupPathExtraData child_extra;
 		RelOptInfo *child_grouped_rel;
 		RelOptInfo *child_partially_grouped_rel;
@@ -7037,23 +7034,20 @@ create_partitionwise_grouping_paths(PlannerInfo *root,
 		 */
 		memcpy(&child_extra, extra, sizeof(child_extra));
 
-		appinfos = find_appinfos_by_relids(root, child_input_rel->relids,
-										   &nappinfos);
-
 		child_target->exprs = (List *)
 			adjust_appendrel_attrs(root,
 								   (Node *) target->exprs,
-								   nappinfos, appinfos);
+								   child_input_rel->relids);
 
 		/* Translate havingQual and targetList. */
 		child_extra.havingQual = (Node *)
 			adjust_appendrel_attrs(root,
 								   extra->havingQual,
-								   nappinfos, appinfos);
+								   child_input_rel->relids);
 		child_extra.targetList = (List *)
 			adjust_appendrel_attrs(root,
 								   (Node *) extra->targetList,
-								   nappinfos, appinfos);
+								   child_input_rel->relids);
 
 		/*
 		 * extra->patype was the value computed for our parent rel; patype is
@@ -7098,8 +7092,6 @@ create_partitionwise_grouping_paths(PlannerInfo *root,
 			grouped_live_children = lappend(grouped_live_children,
 											child_grouped_rel);
 		}
-
-		pfree(appinfos);
 	}
 
 	/*
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 0ab4014be6..630b07d902 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -56,8 +56,7 @@
 typedef struct
 {
 	PlannerInfo *root;
-	int			nappinfos;
-	AppendRelInfo **appinfos;
+	Relids		childrelids;
 } adjust_appendrel_attrs_context;
 
 static RelOptInfo *recurse_set_operations(Node *setOp, PlannerInfo *root,
@@ -119,8 +118,8 @@ static Bitmapset *translate_col_privs(const Bitmapset *parent_privs,
 					List *translated_vars);
 static Node *adjust_appendrel_attrs_mutator(Node *node,
 							   adjust_appendrel_attrs_context *context);
-static Relids adjust_child_relids(Relids relids, int nappinfos,
-					AppendRelInfo **appinfos);
+static Relids adjust_child_relids(PlannerInfo *root, Relids relids,
+					Relids childrelids);
 static List *adjust_inherited_tlist(List *tlist,
 					   AppendRelInfo *context);
 
@@ -2044,18 +2043,16 @@ translate_col_privs(const Bitmapset *parent_privs,
  * maybe we should try to fold the two routines together.
  */
 Node *
-adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos,
-					   AppendRelInfo **appinfos)
+adjust_appendrel_attrs(PlannerInfo *root, Node *node, Relids childrelids)
 {
 	Node	   *result;
 	adjust_appendrel_attrs_context context;
 
 	context.root = root;
-	context.nappinfos = nappinfos;
-	context.appinfos = appinfos;
+	context.childrelids = childrelids;
 
 	/* If there's nothing to adjust, don't call this function. */
-	Assert(nappinfos >= 1 && appinfos != NULL);
+	Assert(!bms_is_empty(childrelids));
 
 	/*
 	 * Must be prepared to start with a Query or a bare expression tree.
@@ -2063,15 +2060,16 @@ adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos,
 	if (node && IsA(node, Query))
 	{
 		Query	   *newnode;
-		int			cnt;
+		int			i;
 
 		newnode = query_tree_mutator((Query *) node,
 									 adjust_appendrel_attrs_mutator,
 									 (void *) &context,
 									 QTW_IGNORE_RC_SUBQUERIES);
-		for (cnt = 0; cnt < nappinfos; cnt++)
+		i = -1;
+		while ((i = bms_next_member(childrelids, i)) >= 0)
 		{
-			AppendRelInfo *appinfo = appinfos[cnt];
+			AppendRelInfo *appinfo = root->append_rel_array[i];
 
 			if (newnode->resultRelation == appinfo->parent_relid)
 			{
@@ -2097,9 +2095,9 @@ static Node *
 adjust_appendrel_attrs_mutator(Node *node,
 							   adjust_appendrel_attrs_context *context)
 {
-	AppendRelInfo **appinfos = context->appinfos;
-	int			nappinfos = context->nappinfos;
-	int			cnt;
+	PlannerInfo *root = context->root;
+	Relids		childrelids = context->childrelids;
+	int			i;
 
 	if (node == NULL)
 		return NULL;
@@ -2108,11 +2106,14 @@ adjust_appendrel_attrs_mutator(Node *node,
 		Var		   *var = (Var *) copyObject(node);
 		AppendRelInfo *appinfo = NULL;
 
-		for (cnt = 0; cnt < nappinfos; cnt++)
+		i = -1;
+		while ((i = bms_next_member(childrelids, i)) >= 0)
 		{
-			if (var->varno == appinfos[cnt]->parent_relid)
+			AppendRelInfo *ainfo = root->append_rel_array[i];
+
+			if (var->varno == ainfo->parent_relid)
 			{
-				appinfo = appinfos[cnt];
+				appinfo = ainfo;
 				break;
 			}
 		}
@@ -2197,9 +2198,10 @@ adjust_appendrel_attrs_mutator(Node *node,
 	{
 		CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
 
-		for (cnt = 0; cnt < nappinfos; cnt++)
+		i = -1;
+		while ((i = bms_next_member(childrelids, i)) >= 0)
 		{
-			AppendRelInfo *appinfo = appinfos[cnt];
+			AppendRelInfo *appinfo = root->append_rel_array[i];
 
 			if (cexpr->cvarno == appinfo->parent_relid)
 			{
@@ -2213,9 +2215,10 @@ adjust_appendrel_attrs_mutator(Node *node,
 	{
 		RangeTblRef *rtr = (RangeTblRef *) copyObject(node);
 
-		for (cnt = 0; cnt < nappinfos; cnt++)
+		i = -1;
+		while ((i = bms_next_member(childrelids, i)) >= 0)
 		{
-			AppendRelInfo *appinfo = appinfos[cnt];
+			AppendRelInfo *appinfo = root->append_rel_array[i];
 
 			if (rtr->rtindex == appinfo->parent_relid)
 			{
@@ -2229,15 +2232,15 @@ adjust_appendrel_attrs_mutator(Node *node,
 	{
 		/* Copy the JoinExpr node with correct mutation of subnodes */
 		JoinExpr   *j;
-		AppendRelInfo *appinfo;
 
 		j = (JoinExpr *) expression_tree_mutator(node,
 												 adjust_appendrel_attrs_mutator,
 												 (void *) context);
 		/* now fix JoinExpr's rtindex (probably never happens) */
-		for (cnt = 0; cnt < nappinfos; cnt++)
+		i = -1;
+		while ((i = bms_next_member(childrelids, i)) >= 0)
 		{
-			appinfo = appinfos[cnt];
+			AppendRelInfo *appinfo = root->append_rel_array[i];
 
 			if (j->rtindex == appinfo->parent_relid)
 			{
@@ -2257,9 +2260,8 @@ adjust_appendrel_attrs_mutator(Node *node,
 														 (void *) context);
 		/* now fix PlaceHolderVar's relid sets */
 		if (phv->phlevelsup == 0)
-			phv->phrels = adjust_child_relids(phv->phrels, context->nappinfos,
-											  context->appinfos);
-		return (Node *) phv;
+			phv->phrels = adjust_child_relids(root, phv->phrels,
+											  context->childrelids);
 	}
 	/* Shouldn't need to handle planner auxiliary nodes here */
 	Assert(!IsA(node, SpecialJoinInfo));
@@ -2289,24 +2291,18 @@ adjust_appendrel_attrs_mutator(Node *node,
 			adjust_appendrel_attrs_mutator((Node *) oldinfo->orclause, context);
 
 		/* adjust relid sets too */
-		newinfo->clause_relids = adjust_child_relids(oldinfo->clause_relids,
-													 context->nappinfos,
-													 context->appinfos);
-		newinfo->required_relids = adjust_child_relids(oldinfo->required_relids,
-													   context->nappinfos,
-													   context->appinfos);
-		newinfo->outer_relids = adjust_child_relids(oldinfo->outer_relids,
-													context->nappinfos,
-													context->appinfos);
-		newinfo->nullable_relids = adjust_child_relids(oldinfo->nullable_relids,
-													   context->nappinfos,
-													   context->appinfos);
-		newinfo->left_relids = adjust_child_relids(oldinfo->left_relids,
-												   context->nappinfos,
-												   context->appinfos);
-		newinfo->right_relids = adjust_child_relids(oldinfo->right_relids,
-													context->nappinfos,
-													context->appinfos);
+		newinfo->clause_relids = adjust_child_relids(root, oldinfo->clause_relids,
+													 context->childrelids);
+		newinfo->required_relids = adjust_child_relids(root, oldinfo->required_relids,
+													   context->childrelids);
+		newinfo->outer_relids = adjust_child_relids(root, oldinfo->outer_relids,
+													context->childrelids);
+		newinfo->nullable_relids = adjust_child_relids(root, oldinfo->nullable_relids,
+													   context->childrelids);
+		newinfo->left_relids = adjust_child_relids(root, oldinfo->left_relids,
+												   context->childrelids);
+		newinfo->right_relids = adjust_child_relids(root, oldinfo->right_relids,
+													context->childrelids);
 
 		/*
 		 * Reset cached derivative fields, since these might need to have
@@ -2344,14 +2340,15 @@ adjust_appendrel_attrs_mutator(Node *node,
  * appinfos specifies the substitutions to be performed.
  */
 static Relids
-adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
+adjust_child_relids(PlannerInfo *root, Relids relids, Relids childrelids)
 {
 	Bitmapset  *result = NULL;
-	int			cnt;
+	int			i;
 
-	for (cnt = 0; cnt < nappinfos; cnt++)
+	i = -1;
+	while ((i = bms_next_member(childrelids, i)) >= 0)
 	{
-		AppendRelInfo *appinfo = appinfos[cnt];
+		AppendRelInfo *appinfo = root->append_rel_array[i];
 
 		/* Remove parent, add child */
 		if (bms_is_member(appinfo->parent_relid, relids))
@@ -2382,12 +2379,10 @@ Relids
 adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
 							   Relids child_relids, Relids top_parent_relids)
 {
-	AppendRelInfo **appinfos;
-	int			nappinfos;
 	Relids		parent_relids = NULL;
 	Relids		result;
 	Relids		tmp_result = NULL;
-	int			cnt;
+	int			i;
 
 	/*
 	 * If the given relids set doesn't contain any of the top parent relids,
@@ -2396,12 +2391,11 @@ adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
 	if (!bms_overlap(relids, top_parent_relids))
 		return relids;
 
-	appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
-
 	/* Construct relids set for the immediate parent of the given child. */
-	for (cnt = 0; cnt < nappinfos; cnt++)
+	i = -1;
+	while ((i = bms_next_member(child_relids, i)) >= 0)
 	{
-		AppendRelInfo *appinfo = appinfos[cnt];
+		AppendRelInfo *appinfo = root->append_rel_array[i];
 
 		parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
 	}
@@ -2415,13 +2409,12 @@ adjust_child_relids_multilevel(PlannerInfo *root, Relids relids,
 		relids = tmp_result;
 	}
 
-	result = adjust_child_relids(relids, nappinfos, appinfos);
+	result = adjust_child_relids(root, relids, child_relids);
 
 	/* Free memory consumed by any intermediate result. */
 	if (tmp_result)
 		bms_free(tmp_result);
 	bms_free(parent_relids);
-	pfree(appinfos);
 
 	return result;
 }
@@ -2535,19 +2528,16 @@ adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
 								  Relids child_relids,
 								  Relids top_parent_relids)
 {
-	AppendRelInfo **appinfos;
 	Bitmapset  *parent_relids = NULL;
-	int			nappinfos;
-	int			cnt;
+	int			i;
 
 	Assert(bms_num_members(child_relids) == bms_num_members(top_parent_relids));
 
-	appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
-
 	/* Construct relids set for the immediate parent of given child. */
-	for (cnt = 0; cnt < nappinfos; cnt++)
+	i = -1;
+	while ((i = bms_next_member(child_relids, i)) >= 0)
 	{
-		AppendRelInfo *appinfo = appinfos[cnt];
+		AppendRelInfo *appinfo = root->append_rel_array[i];
 
 		parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
 	}
@@ -2558,9 +2548,7 @@ adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
 												 top_parent_relids);
 
 	/* Now translate for this child */
-	node = adjust_appendrel_attrs(root, node, nappinfos, appinfos);
-
-	pfree(appinfos);
+	node = adjust_appendrel_attrs(root, node, child_relids);
 
 	return node;
 }
@@ -2575,71 +2563,20 @@ build_child_join_sjinfo(PlannerInfo *root, SpecialJoinInfo *parent_sjinfo,
 						Relids left_relids, Relids right_relids)
 {
 	SpecialJoinInfo *sjinfo = makeNode(SpecialJoinInfo);
-	AppendRelInfo **left_appinfos;
-	int			left_nappinfos;
-	AppendRelInfo **right_appinfos;
-	int			right_nappinfos;
 
 	memcpy(sjinfo, parent_sjinfo, sizeof(SpecialJoinInfo));
-	left_appinfos = find_appinfos_by_relids(root, left_relids,
-											&left_nappinfos);
-	right_appinfos = find_appinfos_by_relids(root, right_relids,
-											 &right_nappinfos);
-
-	sjinfo->min_lefthand = adjust_child_relids(sjinfo->min_lefthand,
-											   left_nappinfos, left_appinfos);
-	sjinfo->min_righthand = adjust_child_relids(sjinfo->min_righthand,
-												right_nappinfos,
-												right_appinfos);
-	sjinfo->syn_lefthand = adjust_child_relids(sjinfo->syn_lefthand,
-											   left_nappinfos, left_appinfos);
-	sjinfo->syn_righthand = adjust_child_relids(sjinfo->syn_righthand,
-												right_nappinfos,
-												right_appinfos);
+
+	sjinfo->min_lefthand = adjust_child_relids(root, sjinfo->min_lefthand,
+											   left_relids);
+	sjinfo->min_righthand = adjust_child_relids(root, sjinfo->min_righthand,
+												right_relids);
+	sjinfo->syn_lefthand = adjust_child_relids(root, sjinfo->syn_lefthand,
+											   left_relids);
+	sjinfo->syn_righthand = adjust_child_relids(root, sjinfo->syn_righthand,
+												right_relids);
 	sjinfo->semi_rhs_exprs = (List *) adjust_appendrel_attrs(root,
 															 (Node *) sjinfo->semi_rhs_exprs,
-															 right_nappinfos,
-															 right_appinfos);
-
-	pfree(left_appinfos);
-	pfree(right_appinfos);
+															 right_relids);
 
 	return sjinfo;
 }
-
-/*
- * find_appinfos_by_relids
- * 		Find AppendRelInfo structures for all relations specified by relids.
- *
- * The AppendRelInfos are returned in an array, which can be pfree'd by the
- * caller. *nappinfos is set to the number of entries in the array.
- */
-AppendRelInfo **
-find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
-{
-	ListCell   *lc;
-	AppendRelInfo **appinfos;
-	int			cnt = 0;
-
-	*nappinfos = bms_num_members(relids);
-	appinfos = (AppendRelInfo **) palloc(sizeof(AppendRelInfo *) * *nappinfos);
-
-	foreach(lc, root->append_rel_list)
-	{
-		AppendRelInfo *appinfo = lfirst(lc);
-
-		if (bms_is_member(appinfo->child_relid, relids))
-		{
-			appinfos[cnt] = appinfo;
-			cnt++;
-
-			/* Stop when we have gathered all the AppendRelInfos. */
-			if (cnt == *nappinfos)
-				return appinfos;
-		}
-	}
-
-	/* Should have found the entries ... */
-	elog(ERROR, "did not find all requested child rels in append_rel_list");
-	return NULL;				/* not reached */
-}
diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c
index c79d0f25d4..2ccf39658f 100644
--- a/src/backend/optimizer/util/placeholder.c
+++ b/src/backend/optimizer/util/placeholder.c
@@ -475,8 +475,6 @@ add_placeholders_to_child_joinrel(PlannerInfo *root, RelOptInfo *childrel,
 								  RelOptInfo *parentrel)
 {
 	ListCell   *lc;
-	AppendRelInfo **appinfos;
-	int			nappinfos;
 
 	Assert(IS_JOIN_REL(childrel) && IS_JOIN_REL(parentrel));
 	Assert(IS_OTHER_REL(childrel));
@@ -485,7 +483,6 @@ add_placeholders_to_child_joinrel(PlannerInfo *root, RelOptInfo *childrel,
 	if (root->placeholder_list == NIL)
 		return;
 
-	appinfos = find_appinfos_by_relids(root, childrel->relids, &nappinfos);
 	foreach(lc, parentrel->reltarget->exprs)
 	{
 		PlaceHolderVar *phv = lfirst(lc);
@@ -501,8 +498,7 @@ add_placeholders_to_child_joinrel(PlannerInfo *root, RelOptInfo *childrel,
 			{
 				phv = (PlaceHolderVar *) adjust_appendrel_attrs(root,
 																(Node *) phv,
-																nappinfos,
-																appinfos);
+																childrel->relids);
 			}
 
 			childrel->reltarget->exprs = lappend(childrel->reltarget->exprs,
@@ -514,6 +510,4 @@ add_placeholders_to_child_joinrel(PlannerInfo *root, RelOptInfo *childrel,
 	childrel->reltarget->cost.startup = parentrel->reltarget->cost.startup;
 	childrel->reltarget->cost.per_tuple = parentrel->reltarget->cost.per_tuple;
 	childrel->reltarget->width = parentrel->reltarget->width;
-
-	pfree(appinfos);
 }
diff --git a/src/backend/optimizer/util/relnode.c b/src/backend/optimizer/util/relnode.c
index 82b78420e7..28edd995cf 100644
--- a/src/backend/optimizer/util/relnode.c
+++ b/src/backend/optimizer/util/relnode.c
@@ -86,6 +86,28 @@ setup_simple_rel_arrays(PlannerInfo *root)
 
 		root->simple_rte_array[rti++] = rte;
 	}
+
+	if (root->append_rel_list != NIL)
+	{
+		root->append_rel_array = (AppendRelInfo **)
+			palloc0(root->simple_rel_array_size * sizeof(AppendRelInfo *));
+
+		foreach(lc, root->append_rel_list)
+		{
+			AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
+			int		child_relid = appinfo->child_relid;
+
+			/* Sanity check */
+			Assert(child_relid < root->simple_rel_array_size);
+
+			if (root->append_rel_array[child_relid])
+				elog(ERROR, "child relation already exists");
+
+			root->append_rel_array[child_relid] = appinfo;
+		}
+	}
+	else
+		root->append_rel_array = NULL;
 }
 
 /*
@@ -689,8 +711,6 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
 					 JoinType jointype)
 {
 	RelOptInfo *joinrel = makeNode(RelOptInfo);
-	AppendRelInfo **appinfos;
-	int			nappinfos;
 
 	/* Only joins between "other" relations land here. */
 	Assert(IS_OTHER_REL(outer_rel) && IS_OTHER_REL(inner_rel));
@@ -759,12 +779,9 @@ build_child_join_rel(PlannerInfo *root, RelOptInfo *outer_rel,
 	add_placeholders_to_child_joinrel(root, joinrel, parent_joinrel);
 
 	/* Construct joininfo list. */
-	appinfos = find_appinfos_by_relids(root, joinrel->relids, &nappinfos);
 	joinrel->joininfo = (List *) adjust_appendrel_attrs(root,
 														(Node *) parent_joinrel->joininfo,
-														nappinfos,
-														appinfos);
-	pfree(appinfos);
+														joinrel->relids);
 
 	/*
 	 * Lateral relids referred in child join will be same as that referred in
diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h
index 3b28d1994f..9045a90f97 100644
--- a/src/include/nodes/relation.h
+++ b/src/include/nodes/relation.h
@@ -151,6 +151,7 @@ typedef struct PlannerGlobal
 #define planner_subplan_get_plan(root, subplan) \
 	((Plan *) list_nth((root)->glob->subplans, (subplan)->plan_id - 1))
 
+struct AppendRelInfo;
 
 /*----------
  * PlannerInfo
@@ -201,6 +202,10 @@ typedef struct PlannerInfo
 	 */
 	RangeTblEntry **simple_rte_array;	/* rangetable as an array */
 
+	struct AppendRelInfo **append_rel_array;	/* append_rel_list indexed by
+												 * child_relid, or NULL if
+												 * append_rel_list is empty */
+
 	/*
 	 * all_baserels is a Relids set of all base relids (but not "other"
 	 * relids) in the query; that is, the Relids identifier of the final join
diff --git a/src/include/optimizer/prep.h b/src/include/optimizer/prep.h
index 38608770a2..acf0740ec6 100644
--- a/src/include/optimizer/prep.h
+++ b/src/include/optimizer/prep.h
@@ -50,15 +50,12 @@ extern RelOptInfo *plan_set_operations(PlannerInfo *root);
 extern void expand_inherited_tables(PlannerInfo *root);
 
 extern Node *adjust_appendrel_attrs(PlannerInfo *root, Node *node,
-					   int nappinfos, AppendRelInfo **appinfos);
+					   Relids childrelids);
 
 extern Node *adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node,
 								  Relids child_relids,
 								  Relids top_parent_relids);
 
-extern AppendRelInfo **find_appinfos_by_relids(PlannerInfo *root,
-						Relids relids, int *nappinfos);
-
 extern SpecialJoinInfo *build_child_join_sjinfo(PlannerInfo *root,
 						SpecialJoinInfo *parent_sjinfo,
 						Relids left_relids, Relids right_relids);
