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

Commitafa0ec3

Browse files
committed
Refactor addition of PlaceHolderVars to joinrel targetlists.
Make build_joinrel_tlist() responsible for adding PHVs that werealready computed in one or the other input relation, and thereforechange add_placeholders_to_joinrel() to only add PHVs that will benewly computed in this joinrel's output. This makes the handlingof PHVs in build_joinrel_tlist() more like its handling of plainVars, which seems like a good thing on intelligibility groundsand will simplify planned future changes. There is a purelycosmetic side-effect that the order of entries in the joinrel'stlist may change; but since it becomes more like the order ofentries in the input tlists, that's not bad.The reason it wasn't done like this originally was the potentialcost of looking up PlaceHolderInfo entries to consult ph_needed.Now that that's O(1) it shouldn't hurt.Discussion:https://postgr.es/m/1405792.1660677844@sss.pgh.pa.us
1 parentb3ff6c7 commitafa0ec3

File tree

3 files changed

+36
-19
lines changed

3 files changed

+36
-19
lines changed

‎src/backend/optimizer/util/placeholder.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -427,14 +427,16 @@ add_placeholders_to_base_rels(PlannerInfo *root)
427427

428428
/*
429429
* add_placeholders_to_joinrel
430-
*Add anyrequired PlaceHolderVars to a join rel's targetlist;
431-
*and iftheycontain lateral references, add those references to the
432-
*joinrel's direct_lateral_relids.
430+
*Add anynewly-computable PlaceHolderVars to a join rel's targetlist;
431+
*and ifcomputable PHVscontain lateral references, add those
432+
*references to thejoinrel's direct_lateral_relids.
433433
*
434434
* A join rel should emit a PlaceHolderVar if (a) the PHV can be computed
435435
* at or below this join level and (b) the PHV is needed above this level.
436-
* However, condition (a) is sufficient to add to direct_lateral_relids,
437-
* as explained below.
436+
* Our caller build_join_rel() has already added any PHVs that were computed
437+
* in either join input rel, so we need add only newly-computable ones to
438+
* the targetlist. However, direct_lateral_relids must be updated for every
439+
* PHV computable at or below this join, as explained below.
438440
*/
439441
void
440442
add_placeholders_to_joinrel(PlannerInfo*root,RelOptInfo*joinrel,
@@ -453,13 +455,10 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
453455
/* Is it still needed above this joinrel? */
454456
if (bms_nonempty_difference(phinfo->ph_needed,relids))
455457
{
456-
/* Yup, add it to the output */
457-
joinrel->reltarget->exprs=lappend(joinrel->reltarget->exprs,
458-
phinfo->ph_var);
459-
joinrel->reltarget->width+=phinfo->ph_width;
460-
461458
/*
462-
* Charge the cost of evaluating the contained expression if
459+
* Yes, but only add to tlist if it wasn't computed in either
460+
* input; otherwise it should be there already. Also, we
461+
* charge the cost of evaluating the contained expression if
463462
* the PHV can be computed here but not in either input. This
464463
* is a bit bogus because we make the decision based on the
465464
* first pair of possible input relations considered for the
@@ -472,12 +471,15 @@ add_placeholders_to_joinrel(PlannerInfo *root, RelOptInfo *joinrel,
472471
if (!bms_is_subset(phinfo->ph_eval_at,outer_rel->relids)&&
473472
!bms_is_subset(phinfo->ph_eval_at,inner_rel->relids))
474473
{
474+
PlaceHolderVar*phv=phinfo->ph_var;
475475
QualCostcost;
476476

477-
cost_qual_eval_node(&cost, (Node*)phinfo->ph_var->phexpr,
478-
root);
477+
joinrel->reltarget->exprs=lappend(joinrel->reltarget->exprs,
478+
phv);
479+
cost_qual_eval_node(&cost, (Node*)phv->phexpr,root);
479480
joinrel->reltarget->cost.startup+=cost.startup;
480481
joinrel->reltarget->cost.per_tuple+=cost.per_tuple;
482+
joinrel->reltarget->width+=phinfo->ph_width;
481483
}
482484
}
483485

‎src/backend/optimizer/util/relnode.c

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -679,8 +679,9 @@ build_join_rel(PlannerInfo *root,
679679
set_foreign_rel_properties(joinrel,outer_rel,inner_rel);
680680

681681
/*
682-
* Create a new tlist containing just the vars that need to be output from
683-
* this join (ie, are needed for higher joinclauses or final output).
682+
* Fill the joinrel's tlist with just the Vars and PHVs that need to be
683+
* output from this join (ie, are needed for higher joinclauses or final
684+
* output).
684685
*
685686
* NOTE: the tlist order for a join rel will depend on which pair of outer
686687
* and inner rels we first try to build it from. But the contents should
@@ -966,6 +967,7 @@ min_join_parameterization(PlannerInfo *root,
966967
* The join's targetlist includes all Vars of its member relations that
967968
* will still be needed above the join. This subroutine adds all such
968969
* Vars from the specified input rel's tlist to the join rel's tlist.
970+
* Likewise for any PlaceHolderVars emitted by the input rel.
969971
*
970972
* We also compute the expected width of the join's output, making use
971973
* of data that was cached at the baserel level by set_rel_width().
@@ -982,11 +984,24 @@ build_joinrel_tlist(PlannerInfo *root, RelOptInfo *joinrel,
982984
Var*var= (Var*)lfirst(vars);
983985

984986
/*
985-
* Ignore PlaceHolderVars in the input tlists; we'll make our own
986-
* decisions about whether to copy them.
987+
* For a PlaceHolderVar, we have to look up the PlaceHolderInfo.
987988
*/
988989
if (IsA(var,PlaceHolderVar))
990+
{
991+
PlaceHolderVar*phv= (PlaceHolderVar*)var;
992+
PlaceHolderInfo*phinfo=find_placeholder_info(root,phv);
993+
994+
/* Is it still needed above this joinrel? */
995+
if (bms_nonempty_difference(phinfo->ph_needed,relids))
996+
{
997+
/* Yup, add it to the output */
998+
joinrel->reltarget->exprs=lappend(joinrel->reltarget->exprs,
999+
phv);
1000+
/* Bubbling up the precomputed result has cost zero */
1001+
joinrel->reltarget->width+=phinfo->ph_width;
1002+
}
9891003
continue;
1004+
}
9901005

9911006
/*
9921007
* Otherwise, anything in a baserel or joinrel targetlist ought to be

‎src/test/regress/expected/join.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5793,10 +5793,10 @@ select * from
57935793
Nested Loop
57945794
Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)), ((COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2)))
57955795
-> Hash Right Join
5796-
Output: c.q1, c.q2, a.q1, a.q2, b.q1,d.q1,(COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
5796+
Output: c.q1, c.q2, a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
57975797
Hash Cond: (d.q1 = c.q2)
57985798
-> Nested Loop
5799-
Output: a.q1, a.q2, b.q1,d.q1,(COALESCE(b.q2, '42'::bigint)), (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
5799+
Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint)), d.q1, (COALESCE((COALESCE(b.q2, '42'::bigint)), d.q2))
58005800
-> Hash Left Join
58015801
Output: a.q1, a.q2, b.q1, (COALESCE(b.q2, '42'::bigint))
58025802
Hash Cond: (a.q2 = b.q1)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp