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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy