diff options
Diffstat (limited to 'src/backend/optimizer/path/indxpath.c')
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 97 |
1 files changed, 73 insertions, 24 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 6f27a191828..e99583ab99c 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.236 2009/02/15 20:16:21 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.237 2009/03/05 23:06:45 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -45,6 +45,14 @@ ((opfamily) == BOOL_BTREE_FAM_OID || (opfamily) == BOOL_HASH_FAM_OID) +/* Whether we are looking for plain indexscan, bitmap scan, or either */ +typedef enum +{ + ST_INDEXSCAN, /* must support amgettuple */ + ST_BITMAPSCAN, /* must support amgetbitmap */ + ST_ANYSCAN /* either is okay */ +} ScanTypeControl; + /* Per-path data used within choose_bitmap_and() */ typedef struct { @@ -58,7 +66,7 @@ typedef struct static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool istoplevel, RelOptInfo *outer_rel, - SaOpControl saop_control); + SaOpControl saop_control, ScanTypeControl scantype); static List *find_saop_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool istoplevel, RelOptInfo *outer_rel); @@ -168,12 +176,16 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) */ indexpaths = find_usable_indexes(root, rel, rel->baserestrictinfo, NIL, - true, NULL, SAOP_FORBID); + true, NULL, SAOP_FORBID, ST_ANYSCAN); /* - * We can submit them all to add_path. (This generates access paths for - * plain IndexScan plans.) However, for the next step we will only want - * the ones that have some selectivity; we must discard anything that was + * Submit all the ones that can form plain IndexScan plans to add_path. + * (A plain IndexPath always represents a plain IndexScan plan; however + * some of the indexes might support only bitmap scans, and those we + * mustn't submit to add_path here.) Also, pick out the ones that might + * be useful as bitmap scans. For that, we must discard indexes that + * don't support bitmap scans, and we also are only interested in paths + * that have some selectivity; we should discard anything that was * generated solely for ordering purposes. */ bitindexpaths = NIL; @@ -181,9 +193,11 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) { IndexPath *ipath = (IndexPath *) lfirst(l); - add_path(rel, (Path *) ipath); + if (ipath->indexinfo->amhasgettuple) + add_path(rel, (Path *) ipath); - if (ipath->indexselectivity < 1.0 && + if (ipath->indexinfo->amhasgetbitmap && + ipath->indexselectivity < 1.0 && !ScanDirectionIsBackward(ipath->indexscandir)) bitindexpaths = lappend(bitindexpaths, ipath); } @@ -254,6 +268,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) * 'outer_rel' is the outer side of the join if forming an inner indexscan * (so some of the given clauses are join clauses); NULL if not * 'saop_control' indicates whether ScalarArrayOpExpr clauses can be used + * 'scantype' indicates whether we need plain or bitmap scan support * * Note: check_partial_indexes() must have been run previously. *---------- @@ -262,7 +277,7 @@ static List * find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, bool istoplevel, RelOptInfo *outer_rel, - SaOpControl saop_control) + SaOpControl saop_control, ScanTypeControl scantype) { Relids outer_relids = outer_rel ? outer_rel->relids : NULL; bool possibly_useful_pathkeys = has_useful_pathkeys(root, rel); @@ -282,6 +297,24 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, bool index_is_ordered; /* + * Check that index supports the desired scan type(s) + */ + switch (scantype) + { + case ST_INDEXSCAN: + if (!index->amhasgettuple) + continue; + break; + case ST_BITMAPSCAN: + if (!index->amhasgetbitmap) + continue; + break; + case ST_ANYSCAN: + /* either or both are OK */ + break; + } + + /* * Ignore partial indexes that do not match the query. If a partial * index is marked predOK then we know it's OK; otherwise, if we are * at top level we know it's not OK (since predOK is exactly whether @@ -445,7 +478,7 @@ find_saop_paths(PlannerInfo *root, RelOptInfo *rel, return find_usable_indexes(root, rel, clauses, outer_clauses, istoplevel, outer_rel, - SAOP_REQUIRE); + SAOP_REQUIRE, ST_BITMAPSCAN); } @@ -507,7 +540,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, all_clauses, false, outer_rel, - SAOP_ALLOW); + SAOP_ALLOW, + ST_BITMAPSCAN); /* Recurse in case there are sub-ORs */ indlist = list_concat(indlist, generate_bitmap_or_paths(root, rel, @@ -524,7 +558,8 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, all_clauses, false, outer_rel, - SAOP_ALLOW); + SAOP_ALLOW, + ST_BITMAPSCAN); } /* @@ -1641,6 +1676,7 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, List *clause_list; List *indexpaths; List *bitindexpaths; + List *allindexpaths; ListCell *l; InnerIndexscanInfo *info; MemoryContext oldcontext; @@ -1736,18 +1772,36 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, * Find all the index paths that are usable for this join, except for * stuff involving OR and ScalarArrayOpExpr clauses. */ - indexpaths = find_usable_indexes(root, rel, - clause_list, NIL, - false, outer_rel, - SAOP_FORBID); + allindexpaths = find_usable_indexes(root, rel, + clause_list, NIL, + false, outer_rel, + SAOP_FORBID, + ST_ANYSCAN); + + /* + * Include the ones that are usable as plain indexscans in indexpaths, and + * include the ones that are usable as bitmap scans in bitindexpaths. + */ + indexpaths = bitindexpaths = NIL; + foreach(l, allindexpaths) + { + IndexPath *ipath = (IndexPath *) lfirst(l); + + if (ipath->indexinfo->amhasgettuple) + indexpaths = lappend(indexpaths, ipath); + + if (ipath->indexinfo->amhasgetbitmap) + bitindexpaths = lappend(bitindexpaths, ipath); + } /* * Generate BitmapOrPaths for any suitable OR-clauses present in the * clause list. */ - bitindexpaths = generate_bitmap_or_paths(root, rel, - clause_list, NIL, - outer_rel); + bitindexpaths = list_concat(bitindexpaths, + generate_bitmap_or_paths(root, rel, + clause_list, NIL, + outer_rel)); /* * Likewise, generate paths using ScalarArrayOpExpr clauses; these can't @@ -1759,11 +1813,6 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, false, outer_rel)); /* - * Include the regular index paths in bitindexpaths. - */ - bitindexpaths = list_concat(bitindexpaths, list_copy(indexpaths)); - - /* * If we found anything usable, generate a BitmapHeapPath for the most * promising combination of bitmap index paths. */ |