Skip to content

Commit 5555351

Browse files
committed
Apply Tomas Vondra's partial-index-only-scan-v5.patch
1 parent fe40821 commit 5555351

File tree

6 files changed

+46
-8
lines changed

6 files changed

+46
-8
lines changed

src/backend/optimizer/path/costsize.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@
8888
#include "optimizer/placeholder.h"
8989
#include "optimizer/plancat.h"
9090
#include "optimizer/planmain.h"
91+
#include "optimizer/predtest.h"
9192
#include "optimizer/restrictinfo.h"
9293
#include "parser/parsetree.h"
9394
#include "utils/lsyscache.h"
@@ -396,7 +397,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
396397
path->path.rows = path->path.param_info->ppi_rows;
397398
/* qpquals come from the rel's restriction clauses and ppi_clauses */
398399
qpquals = list_concat(
399-
extract_nonindex_conditions(baserel->baserestrictinfo,
400+
extract_nonindex_conditions(path->indexrinfos,
400401
path->indexquals),
401402
extract_nonindex_conditions(path->path.param_info->ppi_clauses,
402403
path->indexquals));
@@ -405,7 +406,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
405406
{
406407
path->path.rows = baserel->rows;
407408
/* qpquals come from just the rel's restriction clauses */
408-
qpquals = extract_nonindex_conditions(baserel->baserestrictinfo,
409+
qpquals = extract_nonindex_conditions(path->indexrinfos,
409410
path->indexquals);
410411
}
411412

@@ -609,6 +610,7 @@ extract_nonindex_conditions(List *qual_clauses, List *indexquals)
609610
continue; /* simple duplicate */
610611
if (is_redundant_derived_clause(rinfo, indexquals))
611612
continue; /* derived from same EquivalenceClass */
613+
612614
/* ... skip the predicate proof attempts createplan.c will try ... */
613615
result = lappend(result, rinfo);
614616
}

src/backend/optimizer/path/indxpath.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -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,
129130
static Relids get_bitmap_tree_required_outer(Path *bitmapqual);
130131
static void find_indexpath_quals(Path *bitmapqual, List **quals, List **preds);
131132
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);
133134
static double get_loop_count(PlannerInfo *root, Index cur_relid, Relids outer_relids);
134135
static 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
*/
17841791
static 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,

src/backend/optimizer/plan/planner.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4789,7 +4789,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
47894789

47904790
/* Estimate the cost of index scan */
47914791
indexScanPath = create_index_path(root, indexInfo,
4792-
NIL, NIL, NIL, NIL, NIL,
4792+
NIL, NIL, NIL, NIL, NIL, NIL,
47934793
ForwardScanDirection, false,
47944794
NULL, 1.0);
47954795

src/backend/optimizer/util/pathnode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,7 @@ create_index_path(PlannerInfo *root,
763763
IndexOptInfo *index,
764764
List *indexclauses,
765765
List *indexclausecols,
766+
List *indexrinfos,
766767
List *indexorderbys,
767768
List *indexorderbycols,
768769
List *pathkeys,
@@ -792,6 +793,7 @@ create_index_path(PlannerInfo *root,
792793
pathnode->indexclauses = indexclauses;
793794
pathnode->indexquals = indexquals;
794795
pathnode->indexqualcols = indexqualcols;
796+
pathnode->indexrinfos = indexrinfos;
795797
pathnode->indexorderbys = indexorderbys;
796798
pathnode->indexorderbycols = indexorderbycols;
797799
pathnode->indexscandir = indexscandir;

src/include/nodes/relation.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,10 @@ typedef struct Path
798798
* index column, so 'indexqualcols' must form a nondecreasing sequence.
799799
* (The order of multiple quals for the same index column is unspecified.)
800800
*
801+
* 'indexrinfos' is a list of RestrictInfo nodes from the query's WHERE
802+
* or JOIN conditions, excluding those implied by the index predicate
803+
* (if the index is not partial, the list includes all restriction clauses).
804+
*
801805
* 'indexorderbys', if not NIL, is a list of ORDER BY expressions that have
802806
* been found to be usable as ordering operators for an amcanorderbyop index.
803807
* The list must match the path's pathkeys, ie, one expression per pathkey
@@ -832,6 +836,7 @@ typedef struct IndexPath
832836
List *indexclauses;
833837
List *indexquals;
834838
List *indexqualcols;
839+
List *indexrinfos;
835840
List *indexorderbys;
836841
List *indexorderbycols;
837842
ScanDirection indexscandir;

src/include/optimizer/pathnode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ extern IndexPath *create_index_path(PlannerInfo *root,
3838
IndexOptInfo *index,
3939
List *indexclauses,
4040
List *indexclausecols,
41+
List *indexrinfos,
4142
List *indexorderbys,
4243
List *indexorderbycols,
4344
List *pathkeys,

0 commit comments

Comments
 (0)