1
0
mirror of https://github.com/postgres/postgres.git synced 2025-04-22 23:02:54 +03:00

Fix best_inner_indexscan to actually enforce that an "inner indexscan" use

at least one join condition as an indexqual.  Before bitmap indexscans, this
oversight didn't really cost much except for redundantly considering the
same join paths twice; but as of 8.1 it could result in silly bitmap scans
that would do the same BitmapOr twice and then BitmapAnd these together :-(
This commit is contained in:
Tom Lane 2006-04-08 21:32:25 +00:00
parent cd360f2484
commit 89d75c56db

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.191.2.5 2006/01/29 17:27:49 tgl Exp $ * $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.191.2.6 2006/04/08 21:32:25 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -243,6 +243,10 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
List *all_clauses = NIL; /* not computed till needed */ List *all_clauses = NIL; /* not computed till needed */
ListCell *ilist; ListCell *ilist;
/* quick exit if no available clauses */
if (clauses == NIL)
return NIL;
foreach(ilist, rel->indexlist) foreach(ilist, rel->indexlist)
{ {
IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist); IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist);
@ -1178,16 +1182,20 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
} }
/* /*
* Find all the relevant restriction and join clauses. * Find all the relevant join clauses.
*/ */
clause_list = find_clauses_for_join(root, rel, outer_relids, isouterjoin); clause_list = find_clauses_for_join(root, rel, outer_relids, isouterjoin);
/* /*
* Find all the index paths that are usable for this join, except for * Find all the index paths that are usable for this join, except for
* stuff involving OR clauses. * stuff involving OR clauses. We can use both
* join and restriction clauses as indexquals, but we insist the path
* use at least one join clause (else it'd not be an "inner indexscan"
* but a plain indexscan, and those have already been considered).
*/ */
indexpaths = find_usable_indexes(root, rel, indexpaths = find_usable_indexes(root, rel,
clause_list, NIL, clause_list,
rel->baserestrictinfo,
false, true, false, true,
outer_relids); outer_relids);
@ -1196,7 +1204,8 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
* clause list. * clause list.
*/ */
bitindexpaths = generate_bitmap_or_paths(root, rel, bitindexpaths = generate_bitmap_or_paths(root, rel,
clause_list, NIL, clause_list,
rel->baserestrictinfo,
true, true,
outer_relids); outer_relids);
@ -1246,13 +1255,12 @@ best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
/* /*
* find_clauses_for_join * find_clauses_for_join
* Generate a list of clauses that are potentially useful for * Generate a list of join clauses that are potentially useful for
* scanning rel as the inner side of a nestloop join. * scanning rel as the inner side of a nestloop join.
* *
* We consider both join and restriction clauses. Any joinclause that uses * Any joinclause that uses only otherrels in the specified outer_relids is
* only otherrels in the specified outer_relids is fair game. But there must * fair game. Note that restriction clauses on rel can also be used in
* be at least one such joinclause in the final list, otherwise we return NIL * forming index conditions, but we do not include those here.
* indicating that there isn't any potential win here.
*/ */
static List * static List *
find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel, find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
@ -1280,28 +1288,28 @@ find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
bms_free(join_relids); bms_free(join_relids);
/* if no join clause was matched then forget it, per comments above */ /* quick exit if no join clause was matched */
if (clause_list == NIL) if (clause_list == NIL)
return NIL; return NIL;
/*
* We can also use any plain restriction clauses for the rel. We put
* these at the front of the clause list for the convenience of
* remove_redundant_join_clauses, which can never remove non-join clauses
* and hence won't be able to get rid of a non-join clause if it appears
* after a join clause it is redundant with.
*/
clause_list = list_concat(list_copy(rel->baserestrictinfo), clause_list);
/* /*
* We may now have clauses that are known redundant. Get rid of 'em. * We may now have clauses that are known redundant. Get rid of 'em.
*/ */
if (list_length(clause_list) > 1) if (list_length(clause_list) > 1)
{
clause_list = remove_redundant_join_clauses(root, clause_list = remove_redundant_join_clauses(root,
clause_list, clause_list,
isouterjoin); isouterjoin);
}
/*
* We might have found join clauses that are known redundant with
* restriction clauses on rel (due to conclusions drawn by implied
* equality deduction; without that, this would obviously never happen).
* Get rid of them too.
*/
if (rel->baserestrictinfo != NIL)
clause_list = select_nonredundant_join_clauses(root, clause_list,
rel->baserestrictinfo,
isouterjoin);
return clause_list; return clause_list;
} }