Skip to content

Commit f587749

Browse files
committed
Partial index-only scan patch
1 parent e70501d commit f587749

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
@@ -89,6 +89,7 @@
8989
#include "optimizer/placeholder.h"
9090
#include "optimizer/plancat.h"
9191
#include "optimizer/planmain.h"
92+
#include "optimizer/predtest.h"
9293
#include "optimizer/restrictinfo.h"
9394
#include "parser/parsetree.h"
9495
#include "utils/lsyscache.h"
@@ -429,7 +430,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
429430
path->path.rows = path->path.param_info->ppi_rows;
430431
/* qpquals come from the rel's restriction clauses and ppi_clauses */
431432
qpquals = list_concat(
432-
extract_nonindex_conditions(baserel->baserestrictinfo,
433+
extract_nonindex_conditions(path->indexrinfos,
433434
path->indexquals),
434435
extract_nonindex_conditions(path->path.param_info->ppi_clauses,
435436
path->indexquals));
@@ -438,7 +439,7 @@ cost_index(IndexPath *path, PlannerInfo *root, double loop_count)
438439
{
439440
path->path.rows = baserel->rows;
440441
/* qpquals come from just the rel's restriction clauses */
441-
qpquals = extract_nonindex_conditions(baserel->baserestrictinfo,
442+
qpquals = extract_nonindex_conditions(path->indexrinfos,
442443
path->indexquals);
443444
}
444445

@@ -639,6 +640,7 @@ extract_nonindex_conditions(List *qual_clauses, List *indexquals)
639640
continue; /* simple duplicate */
640641
if (is_redundant_derived_clause(rinfo, indexquals))
641642
continue; /* derived from same EquivalenceClass */
643+
642644
/* ... skip the predicate proof attempts createplan.c will try ... */
643645
result = lappend(result, rinfo);
644646
}

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

@@ -2120,6 +2130,14 @@ match_clauses_to_index(IndexOptInfo *index,
21202130
* If the clause is usable, add it to the appropriate list in *clauseset.
21212131
* *clauseset must be initialized to zeroes before first call.
21222132
*
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+
*
21232141
* Note: in some circumstances we may find the same RestrictInfos coming from
21242142
* multiple places. Defend against redundant outputs by refusing to add a
21252143
* clause twice (pointer equality should be a good enough check for this).
@@ -2136,6 +2154,16 @@ match_clause_to_index(IndexOptInfo *index,
21362154
{
21372155
int indexcol;
21382156

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+
21392167
for (indexcol = 0; indexcol < index->ncolumns; indexcol++)
21402168
{
21412169
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
@@ -4714,7 +4714,7 @@ plan_cluster_use_sort(Oid tableOid, Oid indexOid)
47144714

47154715
/* Estimate the cost of index scan */
47164716
indexScanPath = create_index_path(root, indexInfo,
4717-
NIL, NIL, NIL, NIL, NIL,
4717+
NIL, NIL, NIL, NIL, NIL, NIL,
47184718
ForwardScanDirection, false,
47194719
NULL, 1.0);
47204720

src/backend/optimizer/util/pathnode.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -993,6 +993,7 @@ create_index_path(PlannerInfo *root,
993993
IndexOptInfo *index,
994994
List *indexclauses,
995995
List *indexclausecols,
996+
List *indexrinfos,
996997
List *indexorderbys,
997998
List *indexorderbycols,
998999
List *pathkeys,
@@ -1024,6 +1025,7 @@ create_index_path(PlannerInfo *root,
10241025
pathnode->indexclauses = indexclauses;
10251026
pathnode->indexquals = indexquals;
10261027
pathnode->indexqualcols = indexqualcols;
1028+
pathnode->indexrinfos = indexrinfos;
10271029
pathnode->indexorderbys = indexorderbys;
10281030
pathnode->indexorderbycols = indexorderbycols;
10291031
pathnode->indexscandir = indexscandir;

src/include/nodes/relation.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,6 +805,10 @@ typedef struct Path
805805
* index column, so 'indexqualcols' must form a nondecreasing sequence.
806806
* (The order of multiple quals for the same index column is unspecified.)
807807
*
808+
* 'indexrinfos' is a list of RestrictInfo nodes from the query's WHERE
809+
* or JOIN conditions, excluding those implied by the index predicate
810+
* (if the index is not partial, the list includes all restriction clauses).
811+
*
808812
* 'indexorderbys', if not NIL, is a list of ORDER BY expressions that have
809813
* been found to be usable as ordering operators for an amcanorderbyop index.
810814
* The list must match the path's pathkeys, ie, one expression per pathkey
@@ -839,6 +843,7 @@ typedef struct IndexPath
839843
List *indexclauses;
840844
List *indexquals;
841845
List *indexqualcols;
846+
List *indexrinfos;
842847
List *indexorderbys;
843848
List *indexorderbycols;
844849
ScanDirection indexscandir;

src/include/optimizer/pathnode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ extern IndexPath *create_index_path(PlannerInfo *root,
4141
IndexOptInfo *index,
4242
List *indexclauses,
4343
List *indexclausecols,
44+
List *indexrinfos,
4445
List *indexorderbys,
4546
List *indexorderbycols,
4647
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