Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit43f0c20

Browse files
committed
Fix overoptimistic assumptions in column width estimation for subqueries.
set_append_rel_pathlist supposed that, while computing per-column widthestimates for the appendrel, it could ignore child rels for which thetranslated reltargetlist entry wasn't a Var. This gave rise to completelysilly estimates in some common cases, such as constant outputs from some orall of the arms of a UNION ALL. Instead, fall back on get_typavgwidth toestimate from the value's datatype; which might be a poor estimate but atleast it's not completely wacko.That problem was exposed by an Assert in set_subquery_size_estimates, whichunfortunately was still overoptimistic even with that fix, since we don'tcompute attr_widths estimates for appendrels that are entirely excluded byconstraints. So remove the Assert; we'll just fall back on get_typavgwidthin such cases.Also, since set_subquery_size_estimates calls set_baserel_size_estimateswhich calls set_rel_width, there's no need for set_subquery_size_estimatesto call get_typavgwidth; set_rel_width will handle it for us if we justleave the estimate set to zero. Remove the unnecessary code.Per report from Erik Rijkers and subsequent investigation.
1 parent1af55e2 commit43f0c20

File tree

2 files changed

+44
-22
lines changed

2 files changed

+44
-22
lines changed

‎src/backend/optimizer/path/allpaths.c

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,15 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
403403
continue;
404404
}
405405

406-
/* CE failed, so finish copying targetlist and join quals */
406+
/*
407+
* CE failed, so finish copying/modifying targetlist and join quals.
408+
*
409+
* Note: the resulting childrel->reltargetlist may contain arbitrary
410+
* expressions, which normally would not occur in a reltargetlist.
411+
* That is okay because nothing outside of this routine will look at
412+
* the child rel's reltargetlist. We do have to cope with the case
413+
* while constructing attr_widths estimates below, though.
414+
*/
407415
childrel->joininfo= (List*)
408416
adjust_appendrel_attrs((Node*)rel->joininfo,
409417
appinfo);
@@ -486,23 +494,36 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
486494
parent_rows+=childrel->rows;
487495
parent_size+=childrel->width*childrel->rows;
488496

497+
/*
498+
* Accumulate per-column estimates too. We need not do anything
499+
* for PlaceHolderVars in the parent list. If child expression
500+
* isn't a Var, or we didn't record a width estimate for it, we
501+
* have to fall back on a datatype-based estimate.
502+
*
503+
* By construction, child's reltargetlist is 1-to-1 with parent's.
504+
*/
489505
forboth(parentvars,rel->reltargetlist,
490506
childvars,childrel->reltargetlist)
491507
{
492508
Var*parentvar= (Var*)lfirst(parentvars);
493-
Var*childvar= (Var*)lfirst(childvars);
494-
495-
/*
496-
* Accumulate per-column estimates too. Whole-row Vars and
497-
* PlaceHolderVars can be ignored here.
498-
*/
499-
if (IsA(parentvar,Var)&&
500-
IsA(childvar,Var))
509+
Node*childvar= (Node*)lfirst(childvars);
510+
511+
if (IsA(parentvar,Var))
501512
{
502513
intpndx=parentvar->varattno-rel->min_attr;
503-
intcndx=childvar->varattno-childrel->min_attr;
504-
505-
parent_attrsizes[pndx]+=childrel->attr_widths[cndx]*childrel->rows;
514+
int32child_width=0;
515+
516+
if (IsA(childvar,Var))
517+
{
518+
intcndx= ((Var*)childvar)->varattno-childrel->min_attr;
519+
520+
child_width=childrel->attr_widths[cndx];
521+
}
522+
if (child_width <=0)
523+
child_width=get_typavgwidth(exprType(childvar),
524+
exprTypmod(childvar));
525+
Assert(child_width>0);
526+
parent_attrsizes[pndx]+=child_width*childrel->rows;
506527
}
507528
}
508529
}

‎src/backend/optimizer/path/costsize.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3238,14 +3238,14 @@ set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel,
32383238
/*
32393239
* Compute per-output-column width estimates by examining the subquery's
32403240
* targetlist.For any output that is a plain Var, get the width estimate
3241-
* that was made while planning the subquery. Otherwise,fall back on a
3242-
* datatype-based estimate.
3241+
* that was made while planning the subquery. Otherwise,we leave it to
3242+
*set_rel_width to fill in adatatype-based default estimate.
32433243
*/
32443244
foreach(lc,subroot->parse->targetList)
32453245
{
32463246
TargetEntry*te= (TargetEntry*)lfirst(lc);
32473247
Node*texpr= (Node*)te->expr;
3248-
int32item_width;
3248+
int32item_width=0;
32493249

32503250
Assert(IsA(te,TargetEntry));
32513251
/* junk columns aren't visible to upper query */
@@ -3256,8 +3256,14 @@ set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel,
32563256
* XXX This currently doesn't work for subqueries containing set
32573257
* operations, because the Vars in their tlists are bogus references
32583258
* to the first leaf subquery, which wouldn't give the right answer
3259-
* even if we could still get to its PlannerInfo. So fall back on
3260-
* datatype in that case.
3259+
* even if we could still get to its PlannerInfo.
3260+
*
3261+
* Also, the subquery could be an appendrel for which all branches are
3262+
* known empty due to constraint exclusion, in which case
3263+
* set_append_rel_pathlist will have left the attr_widths set to zero.
3264+
*
3265+
* In either case, we just leave the width estimate zero until
3266+
* set_rel_width fixes it.
32613267
*/
32623268
if (IsA(texpr,Var)&&
32633269
subroot->parse->setOperations==NULL)
@@ -3267,11 +3273,6 @@ set_subquery_size_estimates(PlannerInfo *root, RelOptInfo *rel,
32673273

32683274
item_width=subrel->attr_widths[var->varattno-subrel->min_attr];
32693275
}
3270-
else
3271-
{
3272-
item_width=get_typavgwidth(exprType(texpr),exprTypmod(texpr));
3273-
}
3274-
Assert(item_width>0);
32753276
Assert(te->resno >=rel->min_attr&&te->resno <=rel->max_attr);
32763277
rel->attr_widths[te->resno-rel->min_attr]=item_width;
32773278
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp