]> granicus.if.org Git - postgresql/commitdiff
Second thoughts dept: arrange to cache mergejoin scan selectivity
authorTom Lane <tgl@sss.pgh.pa.us>
Fri, 1 Mar 2002 06:01:20 +0000 (06:01 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Fri, 1 Mar 2002 06:01:20 +0000 (06:01 +0000)
in RestrictInfo nodes, instead of recomputing on every use.

src/backend/nodes/copyfuncs.c
src/backend/nodes/readfuncs.c
src/backend/optimizer/path/costsize.c
src/backend/optimizer/plan/initsplan.c
src/backend/optimizer/prep/prepunion.c
src/include/nodes/relation.h

index 9838d98553176d1e6972603b5009c1d74b6b8d47..570fa28523475d14b970cd0198d25b0a2124ce42 100644 (file)
@@ -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;
index 4414c032150594d283e2cf91607547fc6159496a..7cdd0c73c39aa751aa0bfd670bac3b81d9203c73 100644 (file)
@@ -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;
 
index e50664cf66be4d709da9e97a819209de232983d1..a94d54342e4374ec5fbff0bb50716f374339d555 100644 (file)
@@ -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
index 4c7e281866bc236d76b25790cbd8221a5bb1a7c6..76677b4059caf5b1cb13723c7e5b21e645ec52b4 100644 (file)
@@ -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;
index 03c06b65da770f96d6696584d0ae6a3329b779c6..9b7ea633b6817282069a28c792769d821aecbd05 100644 (file)
@@ -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;
 
index c301d39b2a1527967b4f9412cbe4d8f06bca1430..e14f1ea4e83d672278b59b05f9634bc07e0d3f45 100644 (file)
@@ -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 */