@@ -59,6 +59,7 @@ typedef struct
59
59
bool nonempty ; /* True if lists are not all empty */
60
60
/* Lists of RestrictInfos, one per index column */
61
61
List * indexclauses [INDEX_MAX_KEYS ];
62
+ List * indexrinfos ; /* clauses not implied by predicate */
62
63
} IndexClauseSet ;
63
64
64
65
/* Per-path data used within choose_bitmap_and() */
@@ -129,7 +130,7 @@ static PathClauseUsage *classify_index_clause_usage(Path *path,
129
130
static Relids get_bitmap_tree_required_outer (Path * bitmapqual );
130
131
static void find_indexpath_quals (Path * bitmapqual , List * * quals , List * * preds );
131
132
static 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 );
133
134
static double get_loop_count (PlannerInfo * root , Index cur_relid , Relids outer_relids );
134
135
static double adjust_rowcount_for_semijoins (PlannerInfo * root ,
135
136
Index cur_relid ,
@@ -866,6 +867,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
866
867
double loop_count ;
867
868
List * orderbyclauses ;
868
869
List * orderbyclausecols ;
870
+ List * restrictinfo ;
869
871
List * index_pathkeys ;
870
872
List * useful_pathkeys ;
871
873
bool found_lower_saop_clause ;
@@ -1013,13 +1015,16 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
1013
1015
orderbyclausecols = NIL ;
1014
1016
}
1015
1017
1018
+ restrictinfo
1019
+ = (index -> indpred != NIL ) ? clauses -> indexrinfos : rel -> baserestrictinfo ;
1020
+
1016
1021
/*
1017
1022
* 3. Check if an index-only scan is possible. If we're not building
1018
1023
* plain indexscans, this isn't relevant since bitmap scans don't support
1019
1024
* index data retrieval anyway.
1020
1025
*/
1021
1026
index_only_scan = (scantype != ST_BITMAPSCAN &&
1022
- check_index_only (rel , index ));
1027
+ check_index_only (rel , index , restrictinfo ));
1023
1028
1024
1029
/*
1025
1030
* 4. Generate an indexscan path if there are relevant restriction clauses
@@ -1033,6 +1038,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
1033
1038
ipath = create_index_path (root , index ,
1034
1039
index_clauses ,
1035
1040
clause_columns ,
1041
+ restrictinfo ,
1036
1042
orderbyclauses ,
1037
1043
orderbyclausecols ,
1038
1044
useful_pathkeys ,
@@ -1059,6 +1065,7 @@ build_index_paths(PlannerInfo *root, RelOptInfo *rel,
1059
1065
ipath = create_index_path (root , index ,
1060
1066
index_clauses ,
1061
1067
clause_columns ,
1068
+ restrictinfo ,
1062
1069
NIL ,
1063
1070
NIL ,
1064
1071
useful_pathkeys ,
@@ -1782,7 +1789,7 @@ find_list_position(Node *node, List **nodelist)
1782
1789
* Determine whether an index-only scan is possible for this index.
1783
1790
*/
1784
1791
static bool
1785
- check_index_only (RelOptInfo * rel , IndexOptInfo * index )
1792
+ check_index_only (RelOptInfo * rel , IndexOptInfo * index , List * clauses )
1786
1793
{
1787
1794
bool result ;
1788
1795
Bitmapset * attrs_used = NULL ;
@@ -1814,8 +1821,11 @@ check_index_only(RelOptInfo *rel, IndexOptInfo *index)
1814
1821
*/
1815
1822
pull_varattnos ((Node * ) rel -> reltargetlist , rel -> relid , & attrs_used );
1816
1823
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 )
1819
1829
{
1820
1830
RestrictInfo * rinfo = (RestrictInfo * ) lfirst (lc );
1821
1831
@@ -2120,6 +2130,14 @@ match_clauses_to_index(IndexOptInfo *index,
2120
2130
* If the clause is usable, add it to the appropriate list in *clauseset.
2121
2131
* *clauseset must be initialized to zeroes before first call.
2122
2132
*
2133
+ * For partial indexes we ignore clauses that are implied by the index
2134
+ * predicate - no need to to re-evaluate those, and the columns may not
2135
+ * even be included in the index itself.
2136
+ *
2137
+ * We also build a list of clauses that are not implied by the index
2138
+ * predicate so that we don't need calling predicate_implied_by again
2139
+ * (e.g. in check_index_only).
2140
+ *
2123
2141
* Note: in some circumstances we may find the same RestrictInfos coming from
2124
2142
* multiple places. Defend against redundant outputs by refusing to add a
2125
2143
* clause twice (pointer equality should be a good enough check for this).
@@ -2136,6 +2154,16 @@ match_clause_to_index(IndexOptInfo *index,
2136
2154
{
2137
2155
int indexcol ;
2138
2156
2157
+ if (index -> indpred != NIL )
2158
+ {
2159
+ if (predicate_implied_by (list_make1 (rinfo -> clause ),
2160
+ index -> indpred ))
2161
+ return ;
2162
+
2163
+ /* track non-implied restriction clauses */
2164
+ clauseset -> indexrinfos = lappend (clauseset -> indexrinfos , rinfo );
2165
+ }
2166
+
2139
2167
for (indexcol = 0 ; indexcol < index -> ncolumns ; indexcol ++ )
2140
2168
{
2141
2169
if (match_clause_to_indexcol (index ,
0 commit comments