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

Commitd25ea01

Browse files
committed
Avoid combinatorial explosion in add_child_rel_equivalences().
If an EquivalenceClass member expression includes variables frommultiple appendrels, then instead of producing one substitutedexpression per child relation as intended, we'd create additionalchild expressions for combinations of children of different appendrels.This happened because the child expressions generated while consideringthe first appendrel were taken as sources during substitution of thesecond appendrel, and so on. The extra expressions are useless, and areharmless unless there are too many of them --- but if you have severalappendrels with a thousand or so members each, it gets bad fast.To fix, consider only original (non-em_is_child) EC members as candidatesto be expanded. This requires the ability to substitute directly from atop parent relation's Vars to those of an indirect descendant relation,but we already have that in adjust_appendrel_attrs_multilevel().Per bug #15847 from Feike Steenbergen. This is a longstanding misbehavior,but it's only worth worrying about when there are more appendrel childrenthan we've historically considered wise to use. So I'm not going to takethe risk of back-patching this.Discussion:https://postgr.es/m/15847-ea3734094bf8ae61@postgresql.org
1 parentde87a08 commitd25ea01

File tree

1 file changed

+36
-13
lines changed

1 file changed

+36
-13
lines changed

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

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,11 +2135,10 @@ add_child_rel_equivalences(PlannerInfo *root,
21352135
continue;
21362136

21372137
/*
2138-
* No point in searching if parent relnot mentioned in eclass; but we
2139-
*can't tell that for sure if parent rel is itself a child.
2138+
* No point in searching ifchild's topmostparent relis not
2139+
*mentioned in eclass.
21402140
*/
2141-
if (parent_rel->reloptkind==RELOPT_BASEREL&&
2142-
!bms_is_subset(parent_rel->relids,cur_ec->ec_relids))
2141+
if (!bms_is_subset(child_rel->top_parent_relids,cur_ec->ec_relids))
21432142
continue;
21442143

21452144
foreach(lc2,cur_ec->ec_members)
@@ -2149,18 +2148,41 @@ add_child_rel_equivalences(PlannerInfo *root,
21492148
if (cur_em->em_is_const)
21502149
continue;/* ignore consts here */
21512150

2152-
/* Does it reference parent_rel? */
2153-
if (bms_overlap(cur_em->em_relids,parent_rel->relids))
2151+
/*
2152+
* We consider only original EC members here, not
2153+
* already-transformed child members. Otherwise, if some original
2154+
* member expression references more than one appendrel, we'd get
2155+
* an O(N^2) explosion of useless derived expressions for
2156+
* combinations of children.
2157+
*/
2158+
if (cur_em->em_is_child)
2159+
continue;/* ignore children here */
2160+
2161+
/* Does this member reference child's topmost parent rel? */
2162+
if (bms_overlap(cur_em->em_relids,child_rel->top_parent_relids))
21542163
{
21552164
/* Yes, generate transformed child version */
21562165
Expr*child_expr;
21572166
Relidsnew_relids;
21582167
Relidsnew_nullable_relids;
21592168

2160-
child_expr= (Expr*)
2161-
adjust_appendrel_attrs(root,
2162-
(Node*)cur_em->em_expr,
2163-
1,&appinfo);
2169+
if (parent_rel->reloptkind==RELOPT_BASEREL)
2170+
{
2171+
/* Simple single-level transformation */
2172+
child_expr= (Expr*)
2173+
adjust_appendrel_attrs(root,
2174+
(Node*)cur_em->em_expr,
2175+
1,&appinfo);
2176+
}
2177+
else
2178+
{
2179+
/* Must do multi-level transformation */
2180+
child_expr= (Expr*)
2181+
adjust_appendrel_attrs_multilevel(root,
2182+
(Node*)cur_em->em_expr,
2183+
child_rel->relids,
2184+
child_rel->top_parent_relids);
2185+
}
21642186

21652187
/*
21662188
* Transform em_relids to match. Note we do *not* do
@@ -2169,18 +2191,19 @@ add_child_rel_equivalences(PlannerInfo *root,
21692191
* don't want the child member to be marked as constant.
21702192
*/
21712193
new_relids=bms_difference(cur_em->em_relids,
2172-
parent_rel->relids);
2194+
child_rel->top_parent_relids);
21732195
new_relids=bms_add_members(new_relids,child_rel->relids);
21742196

21752197
/*
21762198
* And likewise for nullable_relids. Note this code assumes
21772199
* parent and child relids are singletons.
21782200
*/
21792201
new_nullable_relids=cur_em->em_nullable_relids;
2180-
if (bms_overlap(new_nullable_relids,parent_rel->relids))
2202+
if (bms_overlap(new_nullable_relids,
2203+
child_rel->top_parent_relids))
21812204
{
21822205
new_nullable_relids=bms_difference(new_nullable_relids,
2183-
parent_rel->relids);
2206+
child_rel->top_parent_relids);
21842207
new_nullable_relids=bms_add_members(new_nullable_relids,
21852208
child_rel->relids);
21862209
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp