Quick hack to allow the outer query's tuple_fraction to be passed down
authorTom Lane
Fri, 10 Jun 2005 03:32:25 +0000 (03:32 +0000)
committerTom Lane
Fri, 10 Jun 2005 03:32:25 +0000 (03:32 +0000)
to a subquery if the outer query is simple enough that the LIMIT can
be reflected directly to the subquery.  This didn't use to be very
interesting, because a subquery that couldn't have been flattened into
the upper query was usually not going to be very responsive to
tuple_fraction anyway.  But with new code that allows UNION ALL subqueries
to pay attention to tuple_fraction, this is useful to do.  In particular
this lets the optimization occur when the UNION ALL is directly inside
a view.

src/backend/optimizer/path/allpaths.c
src/backend/optimizer/plan/planmain.c
src/include/nodes/relation.h

index 4b09f03e6e70623104314120d0a9850e36de8546..25bd55dadf3336812b40f1c2c7069c70e6fbd517 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.133 2005/06/09 04:18:59 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/path/allpaths.c,v 1.134 2005/06/10 03:32:21 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -353,6 +353,28 @@ set_inherited_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
    set_cheapest(rel);
 }
 
+/* quick-and-dirty test to see if any joining is needed */
+static bool
+has_multiple_baserels(PlannerInfo *root)
+{
+   int         num_base_rels = 0;
+   Index       rti;
+
+   for (rti = 1; rti < root->base_rel_array_size; rti++)
+   {
+       RelOptInfo *brel = root->base_rel_array[rti];
+
+       if (brel == NULL)
+           continue;
+
+       /* ignore RTEs that are "other rels" */
+       if (brel->reloptkind == RELOPT_BASEREL)
+           if (++num_base_rels > 1)
+               return true;
+   }
+   return false;
+}
+
 /*
  * set_subquery_pathlist
  *     Build the (single) access path for a subquery RTE
@@ -361,8 +383,10 @@ static void
 set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
                      Index rti, RangeTblEntry *rte)
 {
+   Query      *parse = root->parse;
    Query      *subquery = rte->subquery;
    bool       *differentTypes;
+   double      tuple_fraction;
    List       *pathkeys;
    List       *subquery_pathkeys;
 
@@ -416,8 +440,24 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
 
    pfree(differentTypes);
 
+   /*
+    * We can safely pass the outer tuple_fraction down to the subquery
+    * if the outer level has no joining, aggregation, or sorting to do.
+    * Otherwise we'd better tell the subquery to plan for full retrieval.
+    * (XXX This could probably be made more intelligent ...)
+    */
+   if (parse->hasAggs ||
+       parse->groupClause ||
+       parse->havingQual ||
+       parse->distinctClause ||
+       parse->sortClause ||
+       has_multiple_baserels(root))
+       tuple_fraction = 0.0;   /* default case */
+   else
+       tuple_fraction = root->tuple_fraction;
+
    /* Generate the plan for the subquery */
-   rel->subplan = subquery_planner(subquery, 0.0 /* default case */,
+   rel->subplan = subquery_planner(subquery, tuple_fraction,
                                    &subquery_pathkeys);
 
    /* Copy number of output rows from subplan */
index 50e1bc5ea8c281aea6d86b07a5b6997d08b54426..788fd2f3249e005d8fbd5188a7da18fd3f9ee75c 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * IDENTIFICATION
- *   $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.84 2005/06/08 23:02:04 tgl Exp $
+ *   $PostgreSQL: pgsql/src/backend/optimizer/plan/planmain.c,v 1.85 2005/06/10 03:32:23 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -79,6 +79,9 @@ query_planner(PlannerInfo *root, List *tlist, double tuple_fraction,
    Path       *cheapestpath;
    Path       *sortedpath;
 
+   /* Make tuple_fraction accessible to lower-level routines */
+   root->tuple_fraction = tuple_fraction;
+
    /*
     * If the query has an empty join tree, then it's something easy like
     * "SELECT 2+2;" or "INSERT ... VALUES()".  Fall through quickly.
index ec839d7d3f6aa1db9711d0797ee10d15e47de283..687ef367841abc9f81cbbc62187c4ce6092c7103 100644 (file)
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.113 2005/06/09 04:19:00 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.114 2005/06/10 03:32:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -92,6 +92,8 @@ typedef struct PlannerInfo
    List       *query_pathkeys; /* desired pathkeys for query_planner(),
                                 * and actual pathkeys afterwards */
 
+   double      tuple_fraction; /* tuple_fraction passed to query_planner */
+
    bool        hasJoinRTEs;    /* true if any RTEs are RTE_JOIN kind */
    bool        hasHavingQual;  /* true if havingQual was non-null */
 } PlannerInfo;