Commit 0eb5ab82 authored by Tom Lane's avatar Tom Lane

Apply a MATERIAL node to the result of an uncorrelated subplan, if it

looks like it will save computation to do so.
parent 9f198423
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 @@ ...@@ -18,6 +18,8 @@
#include "nodes/makefuncs.h" #include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h" #include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h" #include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h" #include "optimizer/planner.h"
#include "optimizer/subselect.h" #include "optimizer/subselect.h"
#include "parser/parse_expr.h" #include "parser/parse_expr.h"
...@@ -123,6 +125,7 @@ static Node * ...@@ -123,6 +125,7 @@ static Node *
make_subplan(SubLink *slink) make_subplan(SubLink *slink)
{ {
SubPlan *node = makeNode(SubPlan); SubPlan *node = makeNode(SubPlan);
Query *subquery = (Query *) (slink->subselect);
double tuple_fraction; double tuple_fraction;
Plan *plan; Plan *plan;
List *lst; List *lst;
...@@ -151,8 +154,7 @@ make_subplan(SubLink *slink) ...@@ -151,8 +154,7 @@ make_subplan(SubLink *slink)
else else
tuple_fraction = 0.5; /* 50% */ tuple_fraction = 0.5; /* 50% */
node->plan = plan = union_planner((Query *) slink->subselect, node->plan = plan = union_planner(subquery, tuple_fraction);
tuple_fraction);
/* /*
* Assign subPlan, extParam and locParam to plan nodes. At the moment, * Assign subPlan, extParam and locParam to plan nodes. At the moment,
...@@ -179,7 +181,7 @@ make_subplan(SubLink *slink) ...@@ -179,7 +181,7 @@ make_subplan(SubLink *slink)
PlannerQueryLevel--; PlannerQueryLevel--;
node->plan_id = PlannerPlanId++; node->plan_id = PlannerPlanId++;
node->rtable = ((Query *) slink->subselect)->rtable; node->rtable = subquery->rtable;
node->sublink = slink; node->sublink = slink;
slink->subselect = NULL; /* cool ?! */ slink->subselect = NULL; /* cool ?! */
...@@ -287,12 +289,76 @@ make_subplan(SubLink *slink) ...@@ -287,12 +289,76 @@ make_subplan(SubLink *slink)
} }
else else
{ {
/* make expression of SUBPLAN type */
Expr *expr = makeNode(Expr); Expr *expr = makeNode(Expr);
List *args = NIL; List *args = NIL;
List *newoper = NIL; List *newoper = NIL;
int i = 0; 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->typeOid = BOOLOID; /* bogus, but we don't really care */
expr->opType = SUBPLAN_EXPR; expr->opType = SUBPLAN_EXPR;
expr->oper = (Node *) node; expr->oper = (Node *) node;
......
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