diff options
Diffstat (limited to 'src/backend/optimizer/path/indxpath.c')
-rw-r--r-- | src/backend/optimizer/path/indxpath.c | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index ac6de3d82a5..eaf4e1cb337 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.206 2006/05/18 19:56:46 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.207 2006/06/06 17:59:57 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -47,13 +47,11 @@ static List *find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, - bool istoplevel, bool isjoininner, - Relids outer_relids, + bool istoplevel, RelOptInfo *outer_rel, SaOpControl saop_control); static List *find_saop_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, - bool istoplevel, bool isjoininner, - Relids outer_relids); + bool istoplevel, RelOptInfo *outer_rel); static Path *choose_bitmap_and(PlannerInfo *root, RelOptInfo *rel, List *paths); static int bitmap_path_comparator(const void *a, const void *b); static Cost bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths); @@ -164,7 +162,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) */ indexpaths = find_usable_indexes(root, rel, rel->baserestrictinfo, NIL, - true, false, NULL, SAOP_FORBID); + true, NULL, SAOP_FORBID); /* * We can submit them all to add_path. (This generates access paths for @@ -190,7 +188,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) */ indexpaths = generate_bitmap_or_paths(root, rel, rel->baserestrictinfo, NIL, - false, NULL); + NULL); bitindexpaths = list_concat(bitindexpaths, indexpaths); /* @@ -199,7 +197,7 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) */ indexpaths = find_saop_paths(root, rel, rel->baserestrictinfo, NIL, - true, false, NULL); + true, NULL); bitindexpaths = list_concat(bitindexpaths, indexpaths); /* @@ -247,10 +245,8 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) * 'outer_clauses' is the list of additional upper-level clauses * 'istoplevel' is true if clauses are the rel's top-level restriction list * (outer_clauses must be NIL when this is true) - * 'isjoininner' is true if forming an inner indexscan (so some of the - * given clauses are join clauses) - * 'outer_relids' identifies the outer side of the join (pass NULL - * if not isjoininner) + * '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 * * Note: check_partial_indexes() must have been run previously. @@ -259,10 +255,10 @@ create_index_paths(PlannerInfo *root, RelOptInfo *rel) static List * find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, - bool istoplevel, bool isjoininner, - Relids outer_relids, + bool istoplevel, RelOptInfo *outer_rel, SaOpControl saop_control) { + Relids outer_relids = outer_rel ? outer_rel->relids : NULL; List *result = NIL; List *all_clauses = NIL; /* not computed till needed */ ListCell *ilist; @@ -349,7 +345,7 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, * relevant unless we are at top level. */ index_is_ordered = OidIsValid(index->ordering[0]); - if (istoplevel && index_is_ordered && !isjoininner) + if (index_is_ordered && istoplevel && outer_rel == NULL) { index_pathkeys = build_index_pathkeys(root, index, ForwardScanDirection, @@ -374,7 +370,7 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, index_is_ordered ? ForwardScanDirection : NoMovementScanDirection, - isjoininner); + outer_rel); result = lappend(result, ipath); } @@ -383,7 +379,7 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, * that we failed to match, consider variant ways of achieving the * ordering. Again, this is only interesting at top level. */ - if (istoplevel && index_is_ordered && !isjoininner && + if (index_is_ordered && istoplevel && outer_rel == NULL && root->query_pathkeys != NIL && pathkeys_useful_for_ordering(root, useful_pathkeys) == 0) { @@ -396,7 +392,7 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, restrictclauses, root->query_pathkeys, scandir, - false); + outer_rel); result = lappend(result, ipath); } } @@ -417,8 +413,7 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel, static List * find_saop_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, - bool istoplevel, bool isjoininner, - Relids outer_relids) + bool istoplevel, RelOptInfo *outer_rel) { bool have_saop = false; ListCell *l; @@ -443,8 +438,7 @@ find_saop_paths(PlannerInfo *root, RelOptInfo *rel, return find_usable_indexes(root, rel, clauses, outer_clauses, - istoplevel, isjoininner, - outer_relids, + istoplevel, outer_rel, SAOP_REQUIRE); } @@ -457,13 +451,13 @@ find_saop_paths(PlannerInfo *root, RelOptInfo *rel, * * outer_clauses is a list of additional clauses that can be assumed true * for the purpose of generating indexquals, but are not to be searched for - * ORs. (See find_usable_indexes() for motivation.) + * ORs. (See find_usable_indexes() for motivation.) outer_rel is the outer + * side when we are considering a nestloop inner indexpath. */ List * generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, List *clauses, List *outer_clauses, - bool isjoininner, - Relids outer_relids) + RelOptInfo *outer_rel) { List *result = NIL; List *all_clauses; @@ -506,16 +500,14 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, andargs, all_clauses, false, - isjoininner, - outer_relids, + outer_rel, SAOP_ALLOW); /* Recurse in case there are sub-ORs */ indlist = list_concat(indlist, generate_bitmap_or_paths(root, rel, andargs, all_clauses, - isjoininner, - outer_relids)); + outer_rel)); } else { @@ -525,8 +517,7 @@ generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel, list_make1(orarg), all_clauses, false, - isjoininner, - outer_relids, + outer_rel, SAOP_ALLOW); } @@ -724,7 +715,7 @@ bitmap_and_cost_est(PlannerInfo *root, RelOptInfo *rel, List *paths) cost_bitmap_and_node(&apath, root); /* Now we can do cost_bitmap_heap_scan */ - cost_bitmap_heap_scan(&bpath, root, rel, (Path *) &apath, false); + cost_bitmap_heap_scan(&bpath, root, rel, (Path *) &apath); return bpath.total_cost; } @@ -1338,7 +1329,7 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids) /* * best_inner_indexscan * Finds the best available inner indexscan for a nestloop join - * with the given rel on the inside and the given outer_relids outside. + * with the given rel on the inside and the given outer_rel outside. * May return NULL if there are no possible inner indexscans. * * We ignore ordering considerations (since a nestloop's inner scan's order @@ -1353,8 +1344,9 @@ matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel, Relids outer_relids) */ Path * best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, - Relids outer_relids, JoinType jointype) + RelOptInfo *outer_rel, JoinType jointype) { + Relids outer_relids; Path *cheapest; bool isouterjoin; List *clause_list; @@ -1396,11 +1388,11 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, oldcontext = MemoryContextSwitchTo(GetMemoryChunkContext(rel)); /* - * Intersect the given outer_relids with index_outer_relids to find the + * Intersect the given outer relids with index_outer_relids to find the * set of outer relids actually relevant for this rel. If there are none, * again we can fail immediately. */ - outer_relids = bms_intersect(rel->index_outer_relids, outer_relids); + outer_relids = bms_intersect(rel->index_outer_relids, outer_rel->relids); if (bms_is_empty(outer_relids)) { bms_free(outer_relids); @@ -1413,6 +1405,13 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, * outerrels. (We include the isouterjoin status in the cache lookup key * for safety. In practice I suspect this is not necessary because it * should always be the same for a given innerrel.) + * + * NOTE: because we cache on outer_relids rather than outer_rel->relids, + * we will report the same path and hence path cost for joins with + * different sets of irrelevant rels on the outside. Now that cost_index + * is sensitive to outer_rel->rows, this is not really right. However + * the error is probably not large. Is it worth establishing a separate + * cache entry for each distinct outer_rel->relids set to get this right? */ foreach(l, rel->index_inner_paths) { @@ -1433,9 +1432,9 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, * that could be plain indexscans, ie, they don't require the join context * at all. This may seem redundant, but we need to include those scans in * the input given to choose_bitmap_and() to be sure we find optimal AND - * combinations of join and non-join scans. The worst case is that we - * might return a "best inner indexscan" that's really just a plain - * indexscan, causing some redundant effort in joinpath.c. + * combinations of join and non-join scans. Also, even if the "best + * inner indexscan" is just a plain indexscan, it will have a different + * cost estimate because of cache effects. */ clause_list = find_clauses_for_join(root, rel, outer_relids, isouterjoin); @@ -1445,8 +1444,7 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, */ indexpaths = find_usable_indexes(root, rel, clause_list, NIL, - false, true, - outer_relids, + false, outer_rel, SAOP_FORBID); /* @@ -1455,8 +1453,7 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, */ bitindexpaths = generate_bitmap_or_paths(root, rel, clause_list, NIL, - true, - outer_relids); + outer_rel); /* * Likewise, generate paths using ScalarArrayOpExpr clauses; these can't @@ -1465,8 +1462,7 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel, bitindexpaths = list_concat(bitindexpaths, find_saop_paths(root, rel, clause_list, NIL, - false, true, - outer_relids)); + false, outer_rel)); /* * Include the regular index paths in bitindexpaths. |