diff options
Diffstat (limited to 'src/backend/optimizer/path')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 35 | ||||
-rw-r--r-- | src/backend/optimizer/path/costsize.c | 60 | ||||
-rw-r--r-- | src/backend/optimizer/path/pathkeys.c | 16 |
3 files changed, 67 insertions, 44 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index e6791dddd69..cd04af9f821 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.102 2003/04/24 23:43:09 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.103 2003/06/29 23:05:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -235,6 +235,9 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, RangeTblEntry *childrte; Oid childOID; RelOptInfo *childrel; + List *reltlist; + List *parentvars; + List *childvars; childrte = rt_fetch(childRTindex, root->rtable); childOID = childrte->relid; @@ -251,21 +254,24 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, * Copy the parent's targetlist and restriction quals to the * child, with attribute-number adjustment as needed. We don't * bother to copy the join quals, since we can't do any joining of - * the individual tables. + * the individual tables. Also, we just zap attr_needed rather + * than trying to adjust it; it won't be looked at in the child. */ - childrel->targetlist = (List *) - adjust_inherited_attrs((Node *) rel->targetlist, + reltlist = FastListValue(&rel->reltargetlist); + reltlist = (List *) + adjust_inherited_attrs((Node *) reltlist, parentRTindex, parentOID, childRTindex, childOID); + FastListFromList(&childrel->reltargetlist, reltlist); + childrel->attr_needed = NULL; childrel->baserestrictinfo = (List *) adjust_inherited_attrs((Node *) rel->baserestrictinfo, parentRTindex, parentOID, childRTindex, childOID); - childrel->baserestrictcost = rel->baserestrictcost; /* * Now compute child access paths, and save the cheapest. @@ -274,10 +280,27 @@ set_inherited_rel_pathlist(Query *root, RelOptInfo *rel, subpaths = lappend(subpaths, childrel->cheapest_total_path); - /* Also update total size estimates */ + /* + * Propagate size information from the child back to the parent. + * For simplicity, we use the largest widths from any child as the + * parent estimates. + */ rel->rows += childrel->rows; if (childrel->width > rel->width) rel->width = childrel->width; + + childvars = FastListValue(&childrel->reltargetlist); + foreach(parentvars, FastListValue(&rel->reltargetlist)) + { + Var *parentvar = (Var *) lfirst(parentvars); + Var *childvar = (Var *) lfirst(childvars); + int parentndx = parentvar->varattno - rel->min_attr; + int childndx = childvar->varattno - childrel->min_attr; + + if (childrel->attr_widths[childndx] > rel->attr_widths[parentndx]) + rel->attr_widths[parentndx] = childrel->attr_widths[childndx]; + childvars = lnext(childvars); + } } /* diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 283987b63d5..34a3aaf1c94 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -49,7 +49,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.108 2003/06/29 00:33:43 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.109 2003/06/29 23:05:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1792,13 +1792,9 @@ set_joinrel_size_estimates(Query *root, RelOptInfo *rel, rel->rows = temp; /* - * We could apply set_rel_width() to compute the output tuple width - * from scratch, but at present it's always just the sum of the input - * widths, so why work harder than necessary? If relnode.c is ever - * taught to remove unneeded columns from join targetlists, go back to - * using set_rel_width here. + * We need not compute the output width here, because build_joinrel_tlist + * already did. */ - rel->width = outer_rel->width + inner_rel->width; } /* @@ -1858,13 +1854,16 @@ set_function_size_estimates(Query *root, RelOptInfo *rel) /* * set_rel_width - * Set the estimated output width of the relation. + * Set the estimated output width of a base relation. * - * NB: this works best on base relations because it prefers to look at + * NB: this works best on plain relations because it prefers to look at * real Vars. It will fail to make use of pg_statistic info when applied * to a subquery relation, even if the subquery outputs are simple vars * that we could have gotten info for. Is it worth trying to be smarter * about subqueries? + * + * The per-attribute width estimates are cached for possible re-use while + * building join relations. */ static void set_rel_width(Query *root, RelOptInfo *rel) @@ -1872,38 +1871,41 @@ set_rel_width(Query *root, RelOptInfo *rel) int32 tuple_width = 0; List *tllist; - foreach(tllist, rel->targetlist) + foreach(tllist, FastListValue(&rel->reltargetlist)) { - TargetEntry *tle = (TargetEntry *) lfirst(tllist); + Var *var = (Var *) lfirst(tllist); + int ndx = var->varattno - rel->min_attr; + Oid relid; int32 item_width; - /* - * If it's a Var, try to get statistical info from pg_statistic. - */ - if (tle->expr && IsA(tle->expr, Var)) + Assert(IsA(var, Var)); + + /* The width probably hasn't been cached yet, but may as well check */ + if (rel->attr_widths[ndx] > 0) { - Var *var = (Var *) tle->expr; - Oid relid; + tuple_width += rel->attr_widths[ndx]; + continue; + } - relid = getrelid(var->varno, root->rtable); - if (relid != InvalidOid) + relid = getrelid(var->varno, root->rtable); + if (relid != InvalidOid) + { + item_width = get_attavgwidth(relid, var->varattno); + if (item_width > 0) { - item_width = get_attavgwidth(relid, var->varattno); - if (item_width > 0) - { - tuple_width += item_width; - continue; - } + rel->attr_widths[ndx] = item_width; + tuple_width += item_width; + continue; } } /* - * Not a Var, or can't find statistics for it. Estimate using - * just the type info. + * Not a plain relation, or can't find statistics for it. + * Estimate using just the type info. */ - item_width = get_typavgwidth(tle->resdom->restype, - tle->resdom->restypmod); + item_width = get_typavgwidth(var->vartype, var->vartypmod); Assert(item_width > 0); + rel->attr_widths[ndx] = item_width; tuple_width += item_width; } Assert(tuple_width >= 0); diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c index f8e4906c13b..d4d1179d545 100644 --- a/src/backend/optimizer/path/pathkeys.c +++ b/src/backend/optimizer/path/pathkeys.c @@ -11,7 +11,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.49 2003/05/28 16:03:56 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.50 2003/06/29 23:05:04 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -703,20 +703,18 @@ find_indexkey_var(Query *root, RelOptInfo *rel, AttrNumber varattno) vartypeid; int32 type_mod; - foreach(temp, rel->targetlist) + foreach(temp, FastListValue(&rel->reltargetlist)) { - Var *tle_var = (Var *) ((TargetEntry *) lfirst(temp))->expr; + Var *var = (Var *) lfirst(temp); - if (IsA(tle_var, Var) && - tle_var->varattno == varattno) - return tle_var; + if (IsA(var, Var) && + var->varattno == varattno) + return var; } relid = rel->relid; - Assert(relid > 0); reloid = getrelid(relid, root->rtable); - vartypeid = get_atttype(reloid, varattno); - type_mod = get_atttypmod(reloid, varattno); + get_atttypetypmod(reloid, varattno, &vartypeid, &type_mod); return makeVar(relid, varattno, vartypeid, type_mod, 0); } |