Commit 70fba704 authored by Tom Lane's avatar Tom Lane

Upgrade cost estimation for joins, per discussion with Bradley Baetz.

Try to model the effect of rescanning input tuples in mergejoins;
account for JOIN_IN short-circuiting where appropriate.  Also, recognize
that mergejoin and hashjoin clauses may now be more than single operator
calls, so we have to charge appropriate execution costs.
parent b2773d40
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.47 2003/01/20 18:54:45 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeHashjoin.c,v 1.48 2003/01/27 20:51:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -253,6 +253,13 @@ ExecHashJoin(HashJoinState *node)
return result;
}
}
/* If we didn't return a tuple, may need to set NeedNewOuter */
if (node->js.jointype == JOIN_IN)
{
node->hj_NeedNewOuter = true;
break; /* out of loop over hash bucket */
}
}
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.30 2003/01/20 18:54:46 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/executor/nodeNestloop.c,v 1.31 2003/01/27 20:51:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -254,6 +254,10 @@ ExecNestLoop(NestLoopState *node)
return result;
}
}
/* If we didn't return a tuple, may need to set NeedNewOuter */
if (node->js.jointype == JOIN_IN)
node->nl_NeedNewOuter = true;
}
/*
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.45 2003/01/24 03:58:34 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/nodes/list.c,v 1.46 2003/01/27 20:51:49 tgl Exp $
*
* NOTES
* XXX a few of the following functions are duplicated to handle
......@@ -639,6 +639,28 @@ set_differencei(List *l1, List *l2)
return result;
}
/*
* set_ptrDifference
*
* Same as set_difference, when pointer-equality comparison is sufficient
*/
List *
set_ptrDifference(List *l1, List *l2)
{
List *result = NIL;
List *i;
if (l2 == NIL)
return listCopy(l1); /* slightly faster path for empty l2 */
foreach(i, l1)
{
if (!ptrMember(lfirst(i), l2))
result = lappend(result, lfirst(i));
}
return result;
}
/*
* Reverse a list, non-destructively
*/
......
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.76 2003/01/20 18:54:50 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.77 2003/01/27 20:51:51 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -774,13 +774,6 @@ hash_inner_and_outer(Query *root,
* We examine each restrictinfo clause known for the join to see
* if it is mergejoinable and involves vars from the two sub-relations
* currently of interest.
*
* Since we currently allow only plain Vars as the left and right sides
* of mergejoin clauses, this test is relatively simple. This routine
* would need to be upgraded to support more-complex expressions
* as sides of mergejoins. In theory, we could allow arbitrarily complex
* expressions in mergejoins, so long as one side uses only vars from one
* sub-relation and the other side uses only vars from the other.
*/
static List *
select_mergejoin_clauses(RelOptInfo *joinrel,
......@@ -835,7 +828,9 @@ select_mergejoin_clauses(RelOptInfo *joinrel,
continue; /* not mergejoinable */
/*
* Check if clause is usable with these input rels.
* Check if clause is usable with these input rels. All the vars
* needed on each side of the clause must be available from one or
* the other of the input rels.
*/
if (is_subseti(restrictinfo->left_relids, outerrel->relids) &&
is_subseti(restrictinfo->right_relids, innerrel->relids))
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.85 2003/01/22 00:07:00 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.86 2003/01/27 20:51:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -743,8 +743,7 @@ create_nestloop_path(Query *root,
pathnode->joinrestrictinfo = restrict_clauses;
pathnode->path.pathkeys = pathkeys;
cost_nestloop(&pathnode->path, root, outer_path, inner_path,
restrict_clauses);
cost_nestloop(pathnode, root);
return pathnode;
}
......@@ -816,14 +815,7 @@ create_mergejoin_path(Query *root,
pathnode->outersortkeys = outersortkeys;
pathnode->innersortkeys = innersortkeys;
cost_mergejoin(&pathnode->jpath.path,
root,
outer_path,
inner_path,
restrict_clauses,
mergeclauses,
outersortkeys,
innersortkeys);
cost_mergejoin(pathnode, root);
return pathnode;
}
......@@ -861,12 +853,7 @@ create_hashjoin_path(Query *root,
pathnode->jpath.path.pathkeys = NIL;
pathnode->path_hashclauses = hashclauses;
cost_hashjoin(&pathnode->jpath.path,
root,
outer_path,
inner_path,
restrict_clauses,
hashclauses);
cost_hashjoin(pathnode, root);
return pathnode;
}
......@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.129 2003/01/24 03:58:43 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.130 2003/01/27 20:51:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -2043,6 +2043,8 @@ estimate_num_groups(Query *root, List *groupExprs, double input_rows)
varinfos = newvarinfos;
} while (varinfos != NIL);
numdistinct = ceil(numdistinct);
/* Guard against out-of-range answers */
if (numdistinct > input_rows)
numdistinct = input_rows;
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_list.h,v 1.32 2003/01/24 03:58:43 tgl Exp $
* $Id: pg_list.h,v 1.33 2003/01/27 20:51:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -138,6 +138,7 @@ extern void set_nth(List *l, int n, void *elem);
extern List *set_difference(List *list1, List *list2);
extern List *set_differencei(List *list1, List *list2);
extern List *set_ptrDifference(List *list1, List *list2);
extern List *lreverse(List *l);
extern List *set_union(List *list1, List *list2);
extern List *set_unioni(List *list1, List *list2);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: cost.h,v 1.50 2003/01/12 22:35:29 tgl Exp $
* $Id: cost.h,v 1.51 2003/01/27 20:51:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -71,18 +71,9 @@ extern void cost_group(Path *path, Query *root,
int numGroupCols, double numGroups,
Cost input_startup_cost, Cost input_total_cost,
double input_tuples);
extern void cost_nestloop(Path *path, Query *root,
Path *outer_path, Path *inner_path,
List *restrictlist);
extern void cost_mergejoin(Path *path, Query *root,
Path *outer_path, Path *inner_path,
List *restrictlist,
List *mergeclauses,
List *outersortkeys, List *innersortkeys);
extern void cost_hashjoin(Path *path, Query *root,
Path *outer_path, Path *inner_path,
List *restrictlist,
List *hashclauses);
extern void cost_nestloop(NestPath *path, Query *root);
extern void cost_mergejoin(MergePath *path, Query *root);
extern void cost_hashjoin(HashPath *path, Query *root);
extern void cost_qual_eval(QualCost *cost, List *quals);
extern void set_baserel_size_estimates(Query *root, RelOptInfo *rel);
extern void set_joinrel_size_estimates(Query *root, RelOptInfo *rel,
......
......@@ -58,10 +58,10 @@ SELECT '' AS six, f1 AS "Uncorrelated Field" FROM SUBSELECT_TBL
six | Uncorrelated Field
-----+--------------------
| 1
| 1
| 2
| 2
| 3
| 1
| 2
| 3
(6 rows)
......@@ -71,10 +71,10 @@ SELECT '' AS six, f1 AS "Uncorrelated Field" FROM SUBSELECT_TBL
six | Uncorrelated Field
-----+--------------------
| 1
| 1
| 2
| 2
| 3
| 1
| 2
| 3
(6 rows)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment