@@ -59,6 +59,7 @@ typedef struct
5959 bool nonempty ; /* True if lists are not all empty */
6060 /* Lists of RestrictInfos, one per index column */
6161 List * indexclauses [INDEX_MAX_KEYS ];
62+ List * indexrinfos ; /* clauses not implied by predicate */
6263} IndexClauseSet ;
6364
6465/* Per-path data used within choose_bitmap_and() */
@@ -129,7 +130,7 @@ static PathClauseUsage *classify_index_clause_usage(Path *path,
129130static Relids get_bitmap_tree_required_outer (Path * bitmapqual );
130131static void find_indexpath_quals (Path * bitmapqual , List * * quals , List * * preds );
131132static int find_list_position (Node * node , List * * nodelist );
132- static bool check_index_only (RelOptInfo * rel , IndexOptInfo * index );
133+ static bool check_index_only (RelOptInfo * rel , IndexOptInfo * index , List * clauses );
133134static double get_loop_count (PlannerInfo * root , Index cur_relid , Relids outer_relids );
134135static double adjust_rowcount_for_semijoins (PlannerInfo * root ,
135136 Index cur_relid ,
@@ -866,6 +867,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
866867 double loop_count ;
867868 List * orderbyclauses ;
868869 List * orderbyclausecols ;
870+ List * restrictinfo ;
869871 List * index_pathkeys ;
870872 List * useful_pathkeys ;
871873 bool found_lower_saop_clause ;
@@ -1013,13 +1015,16 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
10131015 orderbyclausecols = NIL ;
10141016 }
10151017
1018+ restrictinfo
1019+ = (index -> indpred != NIL ) ? clauses -> indexrinfos : rel -> baserestrictinfo ;
1020+
10161021 /*
10171022 * 3. Check if an index-only scan is possible. If we're not building
10181023 * plain indexscans, this isn't relevant since bitmap scans don't support
10191024 * index data retrieval anyway.
10201025 */
10211026 index_only_scan = (scantype != ST_BITMAPSCAN &&
1022- check_index_only (rel , index ));
1027+ check_index_only (rel , index , restrictinfo ));
10231028
10241029 /*
10251030 * 4. Generate an indexscan path if there are relevant restriction clauses
@@ -1033,6 +1038,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
10331038 ipath = create_index_path (root , index ,
10341039 index_clauses ,
10351040 clause_columns ,
1041+ restrictinfo ,
10361042 orderbyclauses ,
10371043 orderbyclausecols ,
10381044 useful_pathkeys ,
@@ -1059,6 +1065,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
10591065 ipath = create_index_path (root , index ,
10601066 index_clauses ,
10611067 clause_columns ,
1068+ restrictinfo ,
10621069 NIL ,
10631070 NIL ,
10641071 useful_pathkeys ,
@@ -1782,7 +1789,7 @@ find_list_position(Node *node, List **nodelist)
17821789 * Determine whether an index-only scan is possible for this index.
17831790 */
17841791static bool
1785- check_index_only (RelOptInfo * rel , IndexOptInfo * index )
1792+ check_index_only (RelOptInfo * rel , IndexOptInfo * index , List * clauses )
17861793{
17871794 bool result ;
17881795 Bitmapset * attrs_used = NULL ;
@@ -1814,8 +1821,11 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
18141821 */
18151822 pull_varattnos ((Node * ) rel -> reltargetlist , rel -> relid , & attrs_used );
18161823
1817- /* Add all the attributes used by restriction clauses. */
1818- foreach (lc , rel -> baserestrictinfo )
1824+ /*
1825+ * Add all the attributes used by restriction clauses (only those not
1826+ * implied by the index predicate for partial indexes).
1827+ */
1828+ foreach (lc , clauses )
18191829 {
18201830 RestrictInfo * rinfo = (RestrictInfo * ) lfirst (lc );
18211831
@@ -2141,6 +2151,14 @@ match_clauses_to_index(IndexOptInfo *index,
21412151 * If the clause is usable, add it to the appropriate list in *clauseset.
21422152 * *clauseset must be initialized to zeroes before first call.
21432153 *
2154+ * For partial indexes we ignore clauses that are implied by the index
2155+ * predicate - no need to to re-evaluate those, and the columns may not
2156+ * even be included in the index itself.
2157+ *
2158+ * We also build a list of clauses that are not implied by the index
2159+ * predicate so that we don't need calling predicate_implied_by again
2160+ * (e.g. in check_index_only).
2161+ *
21442162 * Note: in some circumstances we may find the same RestrictInfos coming from
21452163 * multiple places. Defend against redundant outputs by refusing to add a
21462164 * clause twice (pointer equality should be a good enough check for this).
@@ -2157,6 +2175,16 @@ match_clause_to_index(IndexOptInfo *index,
21572175{
21582176 int indexcol ;
21592177
2178+ if (index -> indpred != NIL )
2179+ {
2180+ if (predicate_implied_by (list_make1 (rinfo -> clause ),
2181+ index -> indpred ))
2182+ return ;
2183+
2184+ /* track non-implied restriction clauses */
2185+ clauseset -> indexrinfos = lappend (clauseset -> indexrinfos , rinfo );
2186+ }
2187+
21602188 for (indexcol = 0 ; indexcol < index -> ncolumns ; indexcol ++ )
21612189 {
21622190 if (match_clause_to_indexcol (index ,
0 commit comments