1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-27 12:41:57 +03:00

Teach the planner to remove SubqueryScan nodes from the plan if they

aren't doing anything useful (ie, neither selection nor projection).
Also, extend to SubqueryScan the hacks already in place to avoid
unnecessary ExecProject calls when the result would just be the same
tuple the subquery already delivered.  This saves some overhead in
UNION and other set operations, as well as avoiding overhead for
unflatten-able subqueries.  Per example from Sokolov Yura.
This commit is contained in:
Tom Lane
2005-05-22 22:30:20 +00:00
parent c61207b091
commit e2159f3842
13 changed files with 605 additions and 177 deletions

View File

@ -14,7 +14,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.120 2005/04/06 16:34:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/prep/prepunion.c,v 1.121 2005/05/22 22:30:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -61,6 +61,7 @@ static List *recurse_union_children(Node *setOp, Query *parse,
SetOperationStmt *top_union,
List *refnames_tlist);
static List *generate_setop_tlist(List *colTypes, int flag,
Index varno,
bool hack_constants,
List *input_tlist,
List *refnames_tlist);
@ -119,8 +120,8 @@ plan_set_operations(Query *parse, List **sortClauses)
/*
* Recurse on setOperations tree to generate plans for set ops. The
* final output plan should have just the column types shown as the
* output from the top-level node, plus possibly a resjunk working
* column (we can rely on upper-level nodes to deal with that).
* output from the top-level node, plus possibly resjunk working
* columns (we can rely on upper-level nodes to deal with that).
*/
return recurse_set_operations((Node *) topop, parse,
topop->colTypes, true, -1,
@ -163,7 +164,9 @@ recurse_set_operations(Node *setOp, Query *parse,
* Add a SubqueryScan with the caller-requested targetlist
*/
plan = (Plan *)
make_subqueryscan(generate_setop_tlist(colTypes, flag, true,
make_subqueryscan(generate_setop_tlist(colTypes, flag,
rtr->rtindex,
true,
subplan->targetlist,
refnames_tlist),
NIL,
@ -202,13 +205,15 @@ recurse_set_operations(Node *setOp, Query *parse,
* the subplan. However, since the subplan was generated by
* generate_union_plan() or generate_nonunion_plan(), and hence
* its tlist was generated by generate_append_tlist(), this will
* work.
* work. We just tell generate_setop_tlist() to use varno 0.
*/
if (flag >= 0 ||
!tlist_same_datatypes(plan->targetlist, colTypes, junkOK))
{
plan = (Plan *)
make_result(generate_setop_tlist(colTypes, flag, false,
make_result(generate_setop_tlist(colTypes, flag,
0,
false,
plan->targetlist,
refnames_tlist),
NULL,
@ -415,12 +420,14 @@ recurse_union_children(Node *setOp, Query *parse,
*
* colTypes: column datatypes for non-junk columns
* flag: -1 if no flag column needed, 0 or 1 to create a const flag column
* varno: varno to use in generated Vars
* hack_constants: true to copy up constants (see comments in code)
* input_tlist: targetlist of this node's input node
* refnames_tlist: targetlist to take column names from
*/
static List *
generate_setop_tlist(List *colTypes, int flag,
Index varno,
bool hack_constants,
List *input_tlist,
List *refnames_tlist)
@ -462,7 +469,7 @@ generate_setop_tlist(List *colTypes, int flag,
if (hack_constants && inputtle->expr && IsA(inputtle->expr, Const))
expr = (Node *) inputtle->expr;
else
expr = (Node *) makeVar(0,
expr = (Node *) makeVar(varno,
inputtle->resno,
exprType((Node *) inputtle->expr),
exprTypmod((Node *) inputtle->expr),
@ -513,6 +520,7 @@ generate_setop_tlist(List *colTypes, int flag,
*
* The entries in the Append's targetlist should always be simple Vars;
* we just have to make sure they have the right datatypes and typmods.
* The Vars are always generated with varno 0.
*/
static List *
generate_append_tlist(List *colTypes, bool flag,