From 8f0a9e85b31e67a64604c19a061e91ad1c92b041 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Fri, 1 Mar 2002 06:01:20 +0000 Subject: [PATCH] Second thoughts dept: arrange to cache mergejoin scan selectivity in RestrictInfo nodes, instead of recomputing on every use. --- src/backend/nodes/copyfuncs.c | 4 +++- src/backend/nodes/readfuncs.c | 6 ++++-- src/backend/optimizer/path/costsize.c | 23 ++++++++++++++++------- src/backend/optimizer/plan/initsplan.c | 4 +++- src/backend/optimizer/prep/prepunion.c | 4 +++- src/include/nodes/relation.h | 6 +++++- 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 9838d98553..570fa28523 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -15,7 +15,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.163 2002/02/26 22:47:05 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.164 2002/03/01 06:01:18 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1406,6 +1406,8 @@ _copyRestrictInfo(RestrictInfo *from) */ newnode->left_pathkey = NIL; newnode->right_pathkey = NIL; + newnode->left_mergescansel = from->left_mergescansel; + newnode->right_mergescansel = from->right_mergescansel; newnode->hashjoinoperator = from->hashjoinoperator; newnode->left_bucketsize = from->left_bucketsize; newnode->right_bucketsize = from->right_bucketsize; diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 4414c03215..7cdd0c73c3 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.114 2002/02/26 22:47:07 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.115 2002/03/01 06:01:18 tgl Exp $ * * NOTES * Most of the read functions for plan nodes are tested. (In fact, they @@ -1846,9 +1846,11 @@ _readRestrictInfo(void) local_node->eval_cost = -1; /* ditto for this_selec */ local_node->this_selec = -1; - /* ditto for cached pathkeys and bucketsize */ + /* ditto for cached pathkeys, selectivity, bucketsize */ local_node->left_pathkey = NIL; local_node->right_pathkey = NIL; + local_node->left_mergescansel = -1; + local_node->right_mergescansel = -1; local_node->left_bucketsize = -1; local_node->right_bucketsize = -1; diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index e50664cf66..a94d54342e 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -42,7 +42,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.80 2002/03/01 04:09:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.81 2002/03/01 06:01:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -566,6 +566,7 @@ cost_mergejoin(Path *path, Query *root, Cost startup_cost = 0; Cost run_cost = 0; Cost cpu_per_tuple; + RestrictInfo *firstclause; double outer_rows, inner_rows; double ntuples; @@ -581,10 +582,18 @@ cost_mergejoin(Path *path, Query *root, * Estimate fraction of the left and right inputs that will actually * need to be scanned. We use only the first (most significant) * merge clause for this purpose. + * + * Since this calculation is somewhat expensive, and will be the same + * for all mergejoin paths associated with the merge clause, we cache + * the results in the RestrictInfo node. */ - mergejoinscansel(root, - (Node *) ((RestrictInfo *) lfirst(mergeclauses))->clause, - &leftscan, &rightscan); + firstclause = (RestrictInfo *) lfirst(mergeclauses); + if (firstclause->left_mergescansel < 0) /* not computed yet? */ + mergejoinscansel(root, (Node *) firstclause->clause, + &firstclause->left_mergescansel, + &firstclause->right_mergescansel); + leftscan = firstclause->left_mergescansel; + rightscan = firstclause->right_mergescansel; outer_rows = outer_path->parent->rows * leftscan; inner_rows = inner_path->parent->rows * rightscan; @@ -1099,9 +1108,9 @@ cost_qual_eval_walker(Node *node, Cost *total) * big difference.) * * The "dirty" part comes from the fact that the selectivities of multiple - * clauses are estimated independently and multiplied together. Currently, - * clauselist_selectivity can seldom do any better than that anyhow, but - * someday it might be smarter. + * clauses are estimated independently and multiplied together. Now + * clauselist_selectivity often can't do any better than that anyhow, but + * for some situations (such as range constraints) it is smarter. * * Since we are only using the results to estimate how many potential * output tuples are generated and passed through qpqual checking, it diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 4c7e281866..76677b4059 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.65 2001/10/25 05:49:33 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.66 2002/03/01 06:01:19 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -370,6 +370,8 @@ distribute_qual_to_rels(Query *root, Node *clause, restrictinfo->right_sortop = InvalidOid; restrictinfo->left_pathkey = NIL; /* not computable yet */ restrictinfo->right_pathkey = NIL; + restrictinfo->left_mergescansel = -1; /* not computed until needed */ + restrictinfo->right_mergescansel = -1; restrictinfo->hashjoinoperator = InvalidOid; restrictinfo->left_bucketsize = -1; /* not computed until needed */ restrictinfo->right_bucketsize = -1; diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c index 03c06b65da..9b7ea633b6 100644 --- a/src/backend/optimizer/prep/prepunion.c +++ b/src/backend/optimizer/prep/prepunion.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.69 2001/11/12 20:04:20 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/prep/prepunion.c,v 1.70 2002/03/01 06:01:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -777,6 +777,8 @@ adjust_inherited_attrs_mutator(Node *node, newinfo->this_selec = -1; newinfo->left_pathkey = NIL; /* and these */ newinfo->right_pathkey = NIL; + newinfo->left_mergescansel = -1; + newinfo->right_mergescansel = -1; newinfo->left_bucketsize = -1; newinfo->right_bucketsize = -1; diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index c301d39b2a..e14f1ea4e8 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: relation.h,v 1.61 2001/11/05 17:46:34 momjian Exp $ + * $Id: relation.h,v 1.62 2002/03/01 06:01:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -521,6 +521,10 @@ typedef struct RestrictInfo List *left_pathkey; /* canonical pathkey for left side */ List *right_pathkey; /* canonical pathkey for right side */ + /* cache space for mergeclause processing; -1 if not yet set */ + Selectivity left_mergescansel; /* fraction of left side to scan */ + Selectivity right_mergescansel; /* fraction of right side to scan */ + /* valid if clause is hashjoinable, else InvalidOid: */ Oid hashjoinoperator; /* copy of clause operator */ -- 2.40.0