From: Tom Lane Date: Thu, 2 Mar 2000 04:08:16 +0000 (+0000) Subject: Apply a MATERIAL node to the result of an uncorrelated subplan, if it X-Git-Tag: REL7_0~499 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=0eb5ab8250b0317a3eff4724b4c620856df3abfa;p=postgresql Apply a MATERIAL node to the result of an uncorrelated subplan, if it looks like it will save computation to do so. --- diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index 2790b2740b..eea5b332cf 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.28 2000/02/15 20:49:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/subselect.c,v 1.29 2000/03/02 04:08:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -18,6 +18,8 @@ #include "nodes/makefuncs.h" #include "nodes/nodeFuncs.h" #include "optimizer/clauses.h" +#include "optimizer/cost.h" +#include "optimizer/planmain.h" #include "optimizer/planner.h" #include "optimizer/subselect.h" #include "parser/parse_expr.h" @@ -123,6 +125,7 @@ static Node * make_subplan(SubLink *slink) { SubPlan *node = makeNode(SubPlan); + Query *subquery = (Query *) (slink->subselect); double tuple_fraction; Plan *plan; List *lst; @@ -151,8 +154,7 @@ make_subplan(SubLink *slink) else tuple_fraction = 0.5; /* 50% */ - node->plan = plan = union_planner((Query *) slink->subselect, - tuple_fraction); + node->plan = plan = union_planner(subquery, tuple_fraction); /* * Assign subPlan, extParam and locParam to plan nodes. At the moment, @@ -179,7 +181,7 @@ make_subplan(SubLink *slink) PlannerQueryLevel--; node->plan_id = PlannerPlanId++; - node->rtable = ((Query *) slink->subselect)->rtable; + node->rtable = subquery->rtable; node->sublink = slink; slink->subselect = NULL; /* cool ?! */ @@ -287,12 +289,76 @@ make_subplan(SubLink *slink) } else { - /* make expression of SUBPLAN type */ Expr *expr = makeNode(Expr); List *args = NIL; List *newoper = NIL; int i = 0; + /* + * We can't convert subplans of ALL_SUBLINK or ANY_SUBLINK types to + * initPlans, even when they are uncorrelated or undirect correlated, + * because we need to scan the output of the subplan for each outer + * tuple. However, we have the option to tack a MATERIAL node onto + * the top of an uncorrelated/undirect correlated subplan, which lets + * us do the work of evaluating the subplan only once. We do this + * if the subplan's top plan node is anything more complicated than + * a sequential or index scan, and we do it even for those plan types + * if the qual appears selective enough to eliminate many tuples. + */ + if (node->parParam == NIL) + { + bool use_material; + + switch (nodeTag(plan)) + { + case T_SeqScan: + { + Selectivity qualsel; + + qualsel = clauselist_selectivity(subquery, plan->qual, 0); + /* Is 10% selectivity a good threshold?? */ + use_material = qualsel < 0.10; + break; + } + case T_IndexScan: + { + List *indxqual = ((IndexScan *) plan)->indxqualorig; + Selectivity qualsel; + + qualsel = clauselist_selectivity(subquery, plan->qual, 0); + qualsel *= clauselist_selectivity(subquery, indxqual, 0); + /* Note: if index is lossy, we just double-counted the + * index selectivity. Worth fixing? + */ + /* Is 10% selectivity a good threshold?? */ + use_material = qualsel < 0.10; + break; + } + case T_Material: + case T_Sort: + /* Don't add another Material node if there's one already, + * nor if the top node is a Sort, since Sort materializes + * its output anyway. (I doubt either case can happen in + * practice for a subplan, but...) + */ + use_material = false; + break; + default: + use_material = true; + break; + } + if (use_material) + { + plan = (Plan *) make_noname(plan->targetlist, + NIL, + plan); + node->plan = plan; + } + } + + /* + * Make expression of SUBPLAN type + */ expr->typeOid = BOOLOID; /* bogus, but we don't really care */ expr->opType = SUBPLAN_EXPR; expr->oper = (Node *) node;