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

Commit8edd0e7

Browse files
committed
Suppress Append and MergeAppend plan nodes that have a single child.
If there's only one child relation, the Append or MergeAppend isn'tdoing anything useful, and can be elided. It does have a purposeduring planning though, which is to serve as a buffer between parentand child Var numbering. Therefore we keep it all the way throughto setrefs.c, and get rid of it only after fixing references in theplan level(s) above it. This works largely the same as setrefs.c'sancient hack to get rid of no-op SubqueryScan nodes, and can evenshare some code with that.Note the change to make setrefs.c use apply_tlist_labeling rather thanad-hoc code. This has the effect of propagating the child's resjunkand ressortgroupref labels, which formerly weren't propagated whenremoving a SubqueryScan. Doing that is demonstrably necessary forthe [Merge]Append cases, and seems harmless for SubqueryScan, if onlybecause trivial_subqueryscan is afraid to collapse cases where theresjunk marking differs. (I suspect that restriction could now beremoved, though it's unclear that it'd make any new matches possible,since the outer query can't have references to a child resjunk column.)David Rowley, reviewed by Alvaro Herrera and Tomas VondraDiscussion:https://postgr.es/m/CAKJS1f_7u8ATyJ1JGTMHFoKDvZdeF-iEBhs+sM_SXowOr9cArg@mail.gmail.com
1 parentf21668f commit8edd0e7

File tree

12 files changed

+598
-496
lines changed

12 files changed

+598
-496
lines changed

‎contrib/postgres_fdw/expected/postgres_fdw.out

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8427,17 +8427,16 @@ SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER J
84278427
400 | 400 | 0008
84288428
(4 rows)
84298429

8430-
-- left outer join + nullableclasue
8431-
EXPLAIN (COSTS OFF)
8430+
-- left outer join + nullableclause
8431+
EXPLAIN (VERBOSE,COSTS OFF)
84328432
SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3;
8433-
QUERY PLAN
8434-
-----------------------------------------------------------------------------------
8435-
Sort
8436-
Sort Key: t1.a, ftprt2_p1.b, ftprt2_p1.c
8437-
-> Append
8438-
-> Foreign Scan
8439-
Relations: (public.ftprt1_p1 t1) LEFT JOIN (public.ftprt2_p1 fprt2)
8440-
(5 rows)
8433+
QUERY PLAN
8434+
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
8435+
Foreign Scan
8436+
Output: t1.a, ftprt2_p1.b, ftprt2_p1.c
8437+
Relations: (public.ftprt1_p1 t1) LEFT JOIN (public.ftprt2_p1 fprt2)
8438+
Remote SQL: SELECT r6.a, r9.b, r9.c FROM (public.fprt1_p1 r6 LEFT JOIN public.fprt2_p1 r9 ON (((r6.a = r9.b)) AND ((r6.b = r9.a)) AND ((r9.a < 10)))) WHERE ((r6.a < 10)) ORDER BY r6.a ASC NULLS LAST, r9.b ASC NULLS LAST, r9.c ASC NULLS LAST
8439+
(4 rows)
84418440

84428441
SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3;
84438442
a | b | c

‎contrib/postgres_fdw/sql/postgres_fdw.sql

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2309,8 +2309,8 @@ EXPLAIN (COSTS OFF)
23092309
SELECTt1.a,t2.b,t3.cFROM fprt1 t1INNER JOIN fprt2 t2ON (t1.a=t2.b)INNER JOIN fprt1 t3ON (t2.b=t3.a)WHEREt1.a %25=0ORDER BY1,2,3;
23102310
SELECTt1.a,t2.b,t3.cFROM fprt1 t1INNER JOIN fprt2 t2ON (t1.a=t2.b)INNER JOIN fprt1 t3ON (t2.b=t3.a)WHEREt1.a %25=0ORDER BY1,2,3;
23112311

2312-
-- left outer join + nullableclasue
2313-
EXPLAIN (COSTS OFF)
2312+
-- left outer join + nullableclause
2313+
EXPLAIN (VERBOSE,COSTS OFF)
23142314
SELECTt1.a,t2.b,t2.cFROM fprt1 t1LEFT JOIN (SELECT*FROM fprt2WHERE a<10) t2ON (t1.a=t2.bandt1.b=t2.a)WHEREt1.a<10ORDER BY1,2,3;
23152315
SELECTt1.a,t2.b,t2.cFROM fprt1 t1LEFT JOIN (SELECT*FROM fprt2WHERE a<10) t2ON (t1.a=t2.bandt1.b=t2.a)WHEREt1.a<10ORDER BY1,2,3;
23162316

‎src/backend/executor/execAmi.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,36 @@ ExecSupportsMarkRestore(Path *pathnode)
447447
return false;/* childless Result */
448448
}
449449

450+
caseT_Append:
451+
{
452+
AppendPath*appendPath=castNode(AppendPath,pathnode);
453+
454+
/*
455+
* If there's exactly one child, then there will be no Append
456+
* in the final plan, so we can handle mark/restore if the
457+
* child plan node can.
458+
*/
459+
if (list_length(appendPath->subpaths)==1)
460+
returnExecSupportsMarkRestore((Path*)linitial(appendPath->subpaths));
461+
/* Otherwise, Append can't handle it */
462+
return false;
463+
}
464+
465+
caseT_MergeAppend:
466+
{
467+
MergeAppendPath*mapath=castNode(MergeAppendPath,pathnode);
468+
469+
/*
470+
* Like the Append case above, single-subpath MergeAppends
471+
* won't be in the final plan, so just return the child's
472+
* mark/restore ability.
473+
*/
474+
if (list_length(mapath->subpaths)==1)
475+
returnExecSupportsMarkRestore((Path*)linitial(mapath->subpaths));
476+
/* Otherwise, MergeAppend can't handle it */
477+
return false;
478+
}
479+
450480
default:
451481
break;
452482
}

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

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,8 +1044,8 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
10441044
/*
10451045
* We have to copy the parent's targetlist and quals to the child,
10461046
* with appropriate substitution of variables. If any constant false
1047-
* or NULL clauses turn up, we can disregard the child right away.
1048-
*Ifnot, we can apply constraint exclusion with just the
1047+
* or NULL clauses turn up, we can disregard the child right away. If
1048+
* not, we can apply constraint exclusion with just the
10491049
* baserestrictinfo quals.
10501050
*/
10511051
if (!apply_child_basequals(root,rel,childrel,childRTE,appinfo))
@@ -1708,6 +1708,38 @@ add_paths_to_append_rel(PlannerInfo *root, RelOptInfo *rel,
17081708
required_outer,0, false,
17091709
partitioned_rels,-1));
17101710
}
1711+
1712+
/*
1713+
* When there is only a single child relation, the Append path can inherit
1714+
* any ordering available for the child rel's path, so that it's useful to
1715+
* consider ordered partial paths. Above we only considered the cheapest
1716+
* partial path for each child, but let's also make paths using any
1717+
* partial paths that have pathkeys.
1718+
*/
1719+
if (list_length(live_childrels)==1)
1720+
{
1721+
RelOptInfo*childrel= (RelOptInfo*)linitial(live_childrels);
1722+
1723+
foreach(l,childrel->partial_pathlist)
1724+
{
1725+
Path*path= (Path*)lfirst(l);
1726+
AppendPath*appendpath;
1727+
1728+
/*
1729+
* Skip paths with no pathkeys. Also skip the cheapest partial
1730+
* path, since we already used that above.
1731+
*/
1732+
if (path->pathkeys==NIL||
1733+
path==linitial(childrel->partial_pathlist))
1734+
continue;
1735+
1736+
appendpath=create_append_path(root,rel,NIL,list_make1(path),
1737+
NULL,path->parallel_workers,
1738+
true,
1739+
partitioned_rels,partial_rows);
1740+
add_partial_path(rel, (Path*)appendpath);
1741+
}
1742+
}
17111743
}
17121744

17131745
/*

‎src/backend/optimizer/plan/createplan.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1134,10 +1134,10 @@ create_append_plan(PlannerInfo *root, AppendPath *best_path)
11341134
}
11351135

11361136
/*
1137-
*XXX ideally,if there's just one child,we'd not bother to generate an
1138-
* Appendnode but just return the single child. At the moment this does
1139-
*notwork because the varno of the child scan plan won't match the
1140-
* parent-rel Vars it'll be asked to emit.
1137+
*And build the Append plan. Note thatif there's just one child,the
1138+
* Appendis pretty useless; but we wait till setrefs.c to get rid of it.
1139+
*Doing so here doesn'twork because the varno of the child scan plan
1140+
*won't match theparent-rel Vars it'll be asked to emit.
11411141
*/
11421142

11431143
plan=make_append(subplans,best_path->first_partial_path,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp