diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 9da5444..d257441 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -59,6 +59,7 @@ typedef struct
 	bool		nonempty;		/* True if lists are not all empty */
 	/* Lists of RestrictInfos, one per index column */
 	List	   *indexclauses[INDEX_MAX_KEYS];
+	List	   *rclauses;		/* clauses not implied by predicate */
 } IndexClauseSet;
 
 /* Per-path data used within choose_bitmap_and() */
@@ -129,7 +130,7 @@ static PathClauseUsage *classify_index_clause_usage(Path *path,
 static Relids get_bitmap_tree_required_outer(Path *bitmapqual);
 static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds);
 static int	find_list_position(Node *node, List **nodelist);
-static bool check_index_only(RelOptInfo *rel, IndexOptInfo *index);
+static bool check_index_only(RelOptInfo *rel, IndexOptInfo *index, List *clauses);
 static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids);
 static double adjust_rowcount_for_semijoins(PlannerInfo *root,
 							  Index cur_relid,
@@ -1019,7 +1020,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
 	 * index data retrieval anyway.
 	 */
 	index_only_scan = (scantype != ST_BITMAPSCAN &&
-					   check_index_only(rel, index));
+					   check_index_only(rel, index, clauses->rclauses));
 
 	/*
 	 * 4. Generate an indexscan path if there are relevant restriction clauses
@@ -1782,7 +1783,7 @@ find_list_position(Node *node, List **nodelist)
  *		Determine whether an index-only scan is possible for this index.
  */
 static bool
-check_index_only(RelOptInfo *rel, IndexOptInfo *index)
+check_index_only(RelOptInfo *rel, IndexOptInfo *index, List *clauses)
 {
 	bool		result;
 	Bitmapset  *attrs_used = NULL;
@@ -1790,6 +1791,8 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
 	ListCell   *lc;
 	int			i;
 
+	List	   *rclauses;
+
 	/* Index-only scans must be enabled */
 	if (!enable_indexonlyscan)
 		return false;
@@ -1798,13 +1801,13 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
 	 * Check that all needed attributes of the relation are available from the
 	 * index.
 	 *
-	 * XXX this is overly conservative for partial indexes, since we will
-	 * consider attributes involved in the index predicate as required even
-	 * though the predicate won't need to be checked at runtime.  (The same is
-	 * true for attributes used only in index quals, if we are certain that
-	 * the index is not lossy.)  However, it would be quite expensive to
-	 * determine that accurately at this point, so for now we take the easy
-	 * way out.
+	 * For partial indexes we won't consider attributes involved in clauses
+	 * implied by the index predicate, as those won't be needed at runtime.
+	 *
+	 * XXX The same is true for attributes used only in index quals, if we
+	 * are certain that the index is not lossy. However, it would be quite
+	 * expensive to determine that accurately at this point, so for now we
+	 * take the easy way out.
 	 */
 
 	/*
@@ -1814,8 +1817,17 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
 	 */
 	pull_varattnos((Node *) rel->reltargetlist, rel->relid, &attrs_used);
 
-	/* Add all the attributes used by restriction clauses. */
-	foreach(lc, rel->baserestrictinfo)
+	/*
+	 * For partial indexes use the filtered clauses, otherwise use the
+	 * baserestrictinfo directly for non-partial indexes.
+	 */
+	rclauses = (index->indpred != NIL) ? clauses : rel->baserestrictinfo;
+
+	/*
+	 * Add all the attributes used by restriction clauses (only those not
+	 * implied by the index predicate for partial indexes).
+	 */
+	foreach(lc, rclauses)
 	{
 		RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
 
@@ -2136,6 +2148,30 @@ match_clause_to_index(IndexOptInfo *index,
 {
 	int			indexcol;
 
+
+	/*
+	 * For partial indexes we skip clauses that are implied by the index
+	 * predicate. We don't need to re-evaluate those, and the columns
+	 * may not even be in the index itself, just in the predicate.
+	 *
+	 * We also keep clauses not implied by the index predicate so that 
+	 * check_index_only does not have to call predicate_implied_by again.
+	 * For regular indexes we'll use baserestrictinfo list directly.
+	 *
+	 * XXX We must do this before trying to match the index to index
+	 *     columns, because the index predicates may use columns not
+	 *     used in the index itself.
+	 */
+	if (index->indpred != NIL)
+	{
+		if (predicate_implied_by(list_make1(rinfo->clause),
+								 index->indpred))
+			return;	/* ignore clauses implied by index */
+
+		/* track clauses not implied */
+		clauseset->rclauses = lappend(clauseset->rclauses, rinfo);
+	}
+
 	for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
 	{
 		if (match_clause_to_indexcol(index,
