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

Commite42e312

Browse files
committed
Avoid O(N^2) cost when pulling up lots of UNION ALL subqueries.
perform_pullup_replace_vars() knows how to scan the whole parentquery tree when we are replacing Vars during a subquery flatteningoperation. However, for the specific case of flattening aUNION ALL leaf query, that's mostly wasted work: the only placewhere relevant Vars could exist is in the AppendRelInfo that wejust made for this leaf. Teaching perform_pullup_replace_vars()to just deal with that and exit is worthwhile because, if we haveN such subqueries to pull up, we were spending O(N^2) work uselesslymutating the AppendRelInfos for all the other subqueries.While we're at it, avoid calling substitute_phv_relids if there are noPlaceHolderVars, and remove an obsolete check of parse->hasSubLinks.Andrey Lepikhov and Tom LaneDiscussion:https://postgr.es/m/703c09a2-08f3-d2ec-b33d-dbecd62428b8@postgrespro.ru
1 parent5beb788 commite42e312

File tree

1 file changed

+35
-20
lines changed

1 file changed

+35
-20
lines changed

‎src/backend/optimizer/prep/prepjointree.c

Lines changed: 35 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ static bool find_dependent_phvs_in_jointree(PlannerInfo *root,
128128
Node*node,intvarno);
129129
staticvoidsubstitute_phv_relids(Node*node,
130130
intvarno,Relidssubrelids);
131-
staticvoidfix_append_rel_relids(List*append_rel_list,intvarno,
131+
staticvoidfix_append_rel_relids(PlannerInfo*root,intvarno,
132132
Relidssubrelids);
133133
staticNode*find_jointree_node_for_rel(Node*jtnode,intrelid);
134134

@@ -1232,14 +1232,14 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
12321232
* already checked that this won't require introducing multiple subrelids
12331233
* into the single-slot AppendRelInfo structs.
12341234
*/
1235-
if (parse->hasSubLinks||root->glob->lastPHId!=0||
1236-
root->append_rel_list)
1235+
if (root->glob->lastPHId!=0||root->append_rel_list)
12371236
{
12381237
Relidssubrelids;
12391238

12401239
subrelids=get_relids_in_jointree((Node*)subquery->jointree, false);
1241-
substitute_phv_relids((Node*)parse,varno,subrelids);
1242-
fix_append_rel_relids(root->append_rel_list,varno,subrelids);
1240+
if (root->glob->lastPHId!=0)
1241+
substitute_phv_relids((Node*)parse,varno,subrelids);
1242+
fix_append_rel_relids(root,varno,subrelids);
12431243
}
12441244

12451245
/*
@@ -1418,7 +1418,10 @@ pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex,
14181418

14191419
/*
14201420
* Recursively apply pull_up_subqueries to the new child RTE. (We
1421-
* must build the AppendRelInfo first, because this will modify it.)
1421+
* must build the AppendRelInfo first, because this will modify it;
1422+
* indeed, that's the only part of the upper query where Vars
1423+
* referencing childRTindex can exist at this point.)
1424+
*
14221425
* Note that we can pass NULL for containing-join info even if we're
14231426
* actually under an outer join, because the child's expressions
14241427
* aren't going to propagate up to the join. Also, we ignore the
@@ -2119,6 +2122,25 @@ perform_pullup_replace_vars(PlannerInfo *root,
21192122
Query*parse=root->parse;
21202123
ListCell*lc;
21212124

2125+
/*
2126+
* If we are considering an appendrel child subquery (that is, a UNION ALL
2127+
* member query that we're pulling up), then the only part of the upper
2128+
* query that could reference the child yet is the translated_vars list of
2129+
* the associated AppendRelInfo. Furthermore, we do not need to insert
2130+
* PHVs in the AppendRelInfo --- there isn't any outer join between.
2131+
*/
2132+
if (containing_appendrel)
2133+
{
2134+
boolsave_need_phvs=rvcontext->need_phvs;
2135+
2136+
rvcontext->need_phvs= false;
2137+
containing_appendrel->translated_vars= (List*)
2138+
pullup_replace_vars((Node*)containing_appendrel->translated_vars,
2139+
rvcontext);
2140+
rvcontext->need_phvs=save_need_phvs;
2141+
return;
2142+
}
2143+
21222144
/*
21232145
* Replace all of the top query's references to the subquery's outputs
21242146
* with copies of the adjusted subtlist items, being careful not to
@@ -2172,22 +2194,14 @@ perform_pullup_replace_vars(PlannerInfo *root,
21722194
parse->havingQual=pullup_replace_vars(parse->havingQual,rvcontext);
21732195

21742196
/*
2175-
* Replace references in the translated_vars lists of appendrels. When
2176-
* pulling up an appendrel member, we do not need PHVs in the list of the
2177-
* parent appendrel --- there isn't any outer join between. Elsewhere,
2178-
* use PHVs for safety. (This analysis could be made tighter but it seems
2179-
* unlikely to be worth much trouble.)
2197+
* Replace references in the translated_vars lists of appendrels.
21802198
*/
21812199
foreach(lc,root->append_rel_list)
21822200
{
21832201
AppendRelInfo*appinfo= (AppendRelInfo*)lfirst(lc);
2184-
boolsave_need_phvs=rvcontext->need_phvs;
21852202

2186-
if (appinfo==containing_appendrel)
2187-
rvcontext->need_phvs= false;
21882203
appinfo->translated_vars= (List*)
21892204
pullup_replace_vars((Node*)appinfo->translated_vars,rvcontext);
2190-
rvcontext->need_phvs=save_need_phvs;
21912205
}
21922206

21932207
/*
@@ -3358,7 +3372,7 @@ remove_result_refs(PlannerInfo *root, int varno, Node *newjtloc)
33583372
subrelids=get_relids_in_jointree(newjtloc, false);
33593373
Assert(!bms_is_empty(subrelids));
33603374
substitute_phv_relids((Node*)root->parse,varno,subrelids);
3361-
fix_append_rel_relids(root->append_rel_list,varno,subrelids);
3375+
fix_append_rel_relids(root,varno,subrelids);
33623376
}
33633377

33643378
/*
@@ -3577,7 +3591,7 @@ substitute_phv_relids(Node *node, int varno, Relids subrelids)
35773591
* We assume we may modify the AppendRelInfo nodes in-place.
35783592
*/
35793593
staticvoid
3580-
fix_append_rel_relids(List*append_rel_list,intvarno,Relidssubrelids)
3594+
fix_append_rel_relids(PlannerInfo*root,intvarno,Relidssubrelids)
35813595
{
35823596
ListCell*l;
35833597
intsubvarno=-1;
@@ -3588,7 +3602,7 @@ fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
35883602
* AppendRelInfo nodes refer to it. So compute it on first use. Note that
35893603
* bms_singleton_member will complain if set is not singleton.
35903604
*/
3591-
foreach(l,append_rel_list)
3605+
foreach(l,root->append_rel_list)
35923606
{
35933607
AppendRelInfo*appinfo= (AppendRelInfo*)lfirst(l);
35943608

@@ -3603,8 +3617,9 @@ fix_append_rel_relids(List *append_rel_list, int varno, Relids subrelids)
36033617
}
36043618

36053619
/* Also fix up any PHVs in its translated vars */
3606-
substitute_phv_relids((Node*)appinfo->translated_vars,
3607-
varno,subrelids);
3620+
if (root->glob->lastPHId!=0)
3621+
substitute_phv_relids((Node*)appinfo->translated_vars,
3622+
varno,subrelids);
36083623
}
36093624
}
36103625

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp