Commit a87ee007 authored by Tom Lane's avatar Tom Lane

Quick hack to allow the outer query's tuple_fraction to be passed down

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.
parent 453d74b9
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -353,6 +353,28 @@ set_inherited_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
set_cheapest(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 * set_subquery_pathlist
* Build the (single) access path for a subquery RTE * Build the (single) access path for a subquery RTE
...@@ -361,8 +383,10 @@ static void ...@@ -361,8 +383,10 @@ static void
set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
Index rti, RangeTblEntry *rte) Index rti, RangeTblEntry *rte)
{ {
Query *parse = root->parse;
Query *subquery = rte->subquery; Query *subquery = rte->subquery;
bool *differentTypes; bool *differentTypes;
double tuple_fraction;
List *pathkeys; List *pathkeys;
List *subquery_pathkeys; List *subquery_pathkeys;
...@@ -416,8 +440,24 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel, ...@@ -416,8 +440,24 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
pfree(differentTypes); 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 */ /* Generate the plan for the subquery */
rel->subplan = subquery_planner(subquery, 0.0 /* default case */, rel->subplan = subquery_planner(subquery, tuple_fraction,
&subquery_pathkeys); &subquery_pathkeys);
/* Copy number of output rows from subplan */ /* Copy number of output rows from subplan */
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * 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, ...@@ -79,6 +79,9 @@ query_planner(PlannerInfo *root, List *tlist, double tuple_fraction,
Path *cheapestpath; Path *cheapestpath;
Path *sortedpath; 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 * If the query has an empty join tree, then it's something easy like
* "SELECT 2+2;" or "INSERT ... VALUES()". Fall through quickly. * "SELECT 2+2;" or "INSERT ... VALUES()". Fall through quickly.
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 ...@@ -92,6 +92,8 @@ typedef struct PlannerInfo
List *query_pathkeys; /* desired pathkeys for query_planner(), List *query_pathkeys; /* desired pathkeys for query_planner(),
* and actual pathkeys afterwards */ * and actual pathkeys afterwards */
double tuple_fraction; /* tuple_fraction passed to query_planner */
bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */ bool hasJoinRTEs; /* true if any RTEs are RTE_JOIN kind */
bool hasHavingQual; /* true if havingQual was non-null */ bool hasHavingQual; /* true if havingQual was non-null */
} PlannerInfo; } PlannerInfo;
......
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