diff --git a/src/backend/access/common/tupconvert.c b/src/backend/access/common/tupconvert.c
index 2d0d2f4b32..578bf7f2ba 100644
--- a/src/backend/access/common/tupconvert.c
+++ b/src/backend/access/common/tupconvert.c
@@ -297,6 +297,7 @@ convert_tuples_by_name_map(TupleDesc indesc,
 	AttrNumber *attrMap;
 	int			n;
 	int			i;
+	int			outnondropped = 0;
 
 	n = outdesc->natts;
 	attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
@@ -313,9 +314,22 @@ convert_tuples_by_name_map(TupleDesc indesc,
 		attname = NameStr(outatt->attname);
 		atttypid = outatt->atttypid;
 		atttypmod = outatt->atttypmod;
+
+		/*
+		 * Now search for an attribute with the same name in the indesc. It
+		 * seems likely that a partitioned table will have the attributes in
+		 * the same order as the partition, so we optimistically start our
+		 * search at the same attnum (minus the so-far counted number of
+		 * dropped columns in outdesc).  If a column were dropped in outdesc
+		 * and not indesc then if we didn't account for the dropped column, it
+		 * could mean we end up starting our search one column after the one
+		 * we want to find, resulting in only finding our target on the final
+		 * column we check.
+		 */
 		for (j = 0; j < indesc->natts; j++)
 		{
-			Form_pg_attribute inatt = TupleDescAttr(indesc, j);
+			int k = (outnondropped + j) % indesc->natts;
+			Form_pg_attribute inatt = TupleDescAttr(indesc, k);
 
 			if (inatt->attisdropped)
 				continue;
@@ -330,7 +344,7 @@ convert_tuples_by_name_map(TupleDesc indesc,
 									   attname,
 									   format_type_be(outdesc->tdtypeid),
 									   format_type_be(indesc->tdtypeid))));
-				attrMap[i] = (AttrNumber) (j + 1);
+				attrMap[i] = inatt->attnum;
 				break;
 			}
 		}
@@ -342,6 +356,9 @@ convert_tuples_by_name_map(TupleDesc indesc,
 							   attname,
 							   format_type_be(outdesc->tdtypeid),
 							   format_type_be(indesc->tdtypeid))));
+
+		/* keep track of number of non-dropped outdesc columns */
+		outnondropped++;
 	}
 
 	return attrMap;
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 2d470240d5..5a1e7a12ec 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -51,6 +51,7 @@
 #include "utils/lsyscache.h"
 #include "utils/rel.h"
 #include "utils/selfuncs.h"
+#include "utils/syscache.h"
 
 
 typedef struct
@@ -1896,6 +1897,7 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
 	List	   *vars = NIL;
 	TupleDesc	old_tupdesc = RelationGetDescr(oldrelation);
 	TupleDesc	new_tupdesc = RelationGetDescr(newrelation);
+	Oid			new_relid = RelationGetRelid(newrelation);
 	int			oldnatts = old_tupdesc->natts;
 	int			newnatts = new_tupdesc->natts;
 	int			old_attno;
@@ -1941,7 +1943,7 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
 		 * There's no guarantee it'll have the same column position, because
 		 * of cases like ALTER TABLE ADD COLUMN and multiple inheritance.
 		 * However, in simple cases it will be the same column number, so try
-		 * that before we go groveling through all the columns.
+		 * that before looking for it in syscache.
 		 *
 		 * Note: the test for (att = ...) != NULL cannot fail, it's just a
 		 * notational device to include the assignment into the if-clause.
@@ -1953,16 +1955,16 @@ make_inh_translation_list(Relation oldrelation, Relation newrelation,
 			new_attno = old_attno;
 		else
 		{
-			for (new_attno = 0; new_attno < newnatts; new_attno++)
-			{
-				att = TupleDescAttr(new_tupdesc, new_attno);
-				if (!att->attisdropped &&
-					strcmp(attname, NameStr(att->attname)) == 0)
-					break;
-			}
-			if (new_attno >= newnatts)
+			HeapTuple newtup = SearchSysCacheAttName(new_relid, attname);
+
+			if (!newtup)
 				elog(ERROR, "could not find inherited attribute \"%s\" of relation \"%s\"",
 					 attname, RelationGetRelationName(newrelation));
+
+			new_attno = ((Form_pg_attribute) GETSTRUCT(newtup))->attnum - 1;
+			ReleaseSysCache(newtup);
+
+			att = TupleDescAttr(new_tupdesc, new_attno);
 		}
 
 		/* Found it, check type and collation match */
