mirror of
https://github.com/postgres/postgres.git
synced 2025-11-21 00:42:43 +03:00
Fix cost_nestloop and cost_hashjoin to model the behavior of semi and anti
joins a bit better, ie, understand the differing cost functions for matched and unmatched outer tuples. There is more that could be done in cost_hashjoin but this already helps a great deal. Per discussions with Robert Haas.
This commit is contained in:
@@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.58 2009/04/16 20:42:16 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/restrictinfo.c,v 1.59 2009/05/09 22:51:41 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@@ -35,8 +35,9 @@ static Expr *make_sub_restrictinfos(Expr *clause,
|
||||
bool pseudoconstant,
|
||||
Relids required_relids,
|
||||
Relids nullable_relids);
|
||||
static bool join_clause_is_redundant(PlannerInfo *root,
|
||||
RestrictInfo *rinfo,
|
||||
static List *select_nonredundant_join_list(List *restrictinfo_list,
|
||||
List *reference_list);
|
||||
static bool join_clause_is_redundant(RestrictInfo *rinfo,
|
||||
List *reference_list);
|
||||
|
||||
|
||||
@@ -545,26 +546,91 @@ extract_actual_join_clauses(List *restrictinfo_list,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* select_nonredundant_join_clauses
|
||||
*
|
||||
* Given a list of RestrictInfo clauses that are to be applied in a join,
|
||||
* select the ones that are not redundant with any clause in the
|
||||
* reference_list. This is used only for nestloop-with-inner-indexscan
|
||||
* joins: any clauses being checked by the index should be removed from
|
||||
* the qpquals list.
|
||||
* select the ones that are not redundant with any clause that's enforced
|
||||
* by the inner_path. This is used for nestloop joins, wherein any clause
|
||||
* being used in an inner indexscan need not be checked again at the join.
|
||||
*
|
||||
* "Redundant" means either equal() or derived from the same EquivalenceClass.
|
||||
* We have to check the latter because indxqual.c may select different derived
|
||||
* clauses than were selected by generate_join_implied_equalities().
|
||||
*
|
||||
* Note that we assume the given restrictinfo_list has already been checked
|
||||
* for local redundancies, so we don't check again.
|
||||
* Note that we are *not* checking for local redundancies within the given
|
||||
* restrictinfo_list; that should have been handled elsewhere.
|
||||
*/
|
||||
List *
|
||||
select_nonredundant_join_clauses(PlannerInfo *root,
|
||||
List *restrictinfo_list,
|
||||
List *reference_list)
|
||||
Path *inner_path)
|
||||
{
|
||||
if (IsA(inner_path, IndexPath))
|
||||
{
|
||||
/*
|
||||
* Check the index quals to see if any of them are join clauses.
|
||||
*
|
||||
* We can skip this if the index path is an ordinary indexpath and not
|
||||
* a special innerjoin path, since it then wouldn't be using any join
|
||||
* clauses.
|
||||
*/
|
||||
IndexPath *innerpath = (IndexPath *) inner_path;
|
||||
|
||||
if (innerpath->isjoininner)
|
||||
restrictinfo_list =
|
||||
select_nonredundant_join_list(restrictinfo_list,
|
||||
innerpath->indexclauses);
|
||||
}
|
||||
else if (IsA(inner_path, BitmapHeapPath))
|
||||
{
|
||||
/*
|
||||
* Same deal for bitmapped index scans.
|
||||
*
|
||||
* Note: both here and above, we ignore any implicit index
|
||||
* restrictions associated with the use of partial indexes. This is
|
||||
* OK because we're only trying to prove we can dispense with some
|
||||
* join quals; failing to prove that doesn't result in an incorrect
|
||||
* plan. It's quite unlikely that a join qual could be proven
|
||||
* redundant by an index predicate anyway. (Also, if we did manage
|
||||
* to prove it, we'd have to have a special case for update targets;
|
||||
* see notes about EvalPlanQual testing in create_indexscan_plan().)
|
||||
*/
|
||||
BitmapHeapPath *innerpath = (BitmapHeapPath *) inner_path;
|
||||
|
||||
if (innerpath->isjoininner)
|
||||
{
|
||||
List *bitmapclauses;
|
||||
|
||||
bitmapclauses =
|
||||
make_restrictinfo_from_bitmapqual(innerpath->bitmapqual,
|
||||
true,
|
||||
false);
|
||||
restrictinfo_list =
|
||||
select_nonredundant_join_list(restrictinfo_list,
|
||||
bitmapclauses);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX the inner path of a nestloop could also be an append relation
|
||||
* whose elements use join quals. However, they might each use different
|
||||
* quals; we could only remove join quals that are enforced by all the
|
||||
* appendrel members. For the moment we don't bother to try.
|
||||
*/
|
||||
|
||||
return restrictinfo_list;
|
||||
}
|
||||
|
||||
/*
|
||||
* select_nonredundant_join_list
|
||||
* Select the members of restrictinfo_list that are not redundant with
|
||||
* any member of reference_list. See above for more info.
|
||||
*/
|
||||
static List *
|
||||
select_nonredundant_join_list(List *restrictinfo_list,
|
||||
List *reference_list)
|
||||
{
|
||||
List *result = NIL;
|
||||
ListCell *item;
|
||||
@@ -574,7 +640,7 @@ select_nonredundant_join_clauses(PlannerInfo *root,
|
||||
RestrictInfo *rinfo = (RestrictInfo *) lfirst(item);
|
||||
|
||||
/* drop it if redundant with any reference clause */
|
||||
if (join_clause_is_redundant(root, rinfo, reference_list))
|
||||
if (join_clause_is_redundant(rinfo, reference_list))
|
||||
continue;
|
||||
|
||||
/* otherwise, add it to result list */
|
||||
@@ -589,8 +655,7 @@ select_nonredundant_join_clauses(PlannerInfo *root,
|
||||
* Test whether rinfo is redundant with any clause in reference_list.
|
||||
*/
|
||||
static bool
|
||||
join_clause_is_redundant(PlannerInfo *root,
|
||||
RestrictInfo *rinfo,
|
||||
join_clause_is_redundant(RestrictInfo *rinfo,
|
||||
List *reference_list)
|
||||
{
|
||||
ListCell *refitem;
|
||||
|
||||
Reference in New Issue
Block a user