@@ -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
@@ -2141,6 +2151,14 @@ match_clauses_to_index(IndexOptInfo *index,
2141
2151
* If the clause is usable, add it to the appropriate list in *clauseset.
2142
2152
* *clauseset must be initialized to zeroes before first call.
2143
2153
*
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
+ *
2144
2162
* Note: in some circumstances we may find the same RestrictInfos coming from
2145
2163
* multiple places. Defend against redundant outputs by refusing to add a
2146
2164
* clause twice (pointer equality should be a good enough check for this).
@@ -2157,6 +2175,16 @@ match_clause_to_index(IndexOptInfo *index,
2157
2175
{
2158
2176
int indexcol ;
2159
2177
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
+
2160
2188
for (indexcol = 0 ; indexcol < index -> ncolumns ; indexcol ++ )
2161
2189
{
2162
2190
if (match_clause_to_indexcol (index ,
0 commit comments