Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 4ea9948

Browse files
committed
Fix up parallel-safety marking for appendrels.
The previous coding assumed that the value derived by set_rel_consider_parallel() for an appendrel parent would be accurate for all the appendrel's children; but this is not so, for example because one child might scan a temp table. Instead, apply set_rel_consider_parallel() to each child rel as well as the parent, and then take the AND of the results as controlling parallel safety for the appendrel as a whole. (We might someday be able to deal more intelligently than this with cases in which some of the childrels are parallel-safe and others not, but that's for later.) Robert Haas and Tom Lane
1 parent 2c6e647 commit 4ea9948

File tree

1 file changed

+58
-15
lines changed

1 file changed

+58
-15
lines changed

src/backend/optimizer/path/allpaths.c

+58-15
Original file line numberDiff line numberDiff line change
@@ -165,8 +165,8 @@ make_one_rel(PlannerInfo *root, List *joinlist)
165165
set_base_rel_consider_startup(root);
166166

167167
/*
168-
* Generate access paths for the base rels. set_base_rel_sizes also sets
169-
* the consider_parallel flag for each baserel, if appropriate.
168+
* Compute size estimates and consider_parallel flags for each base rel,
169+
* then generate access paths.
170170
*/
171171
set_base_rel_sizes(root);
172172
set_base_rel_pathlists(root);
@@ -234,7 +234,7 @@ set_base_rel_consider_startup(PlannerInfo *root)
234234
*
235235
* We do this in a separate pass over the base rels so that rowcount
236236
* estimates are available for parameterized path generation, and also so
237-
* that the consider_parallel flag is set correctly before we begin to
237+
* that each rel's consider_parallel flag is set correctly before we begin to
238238
* generate paths.
239239
*/
240240
static void
@@ -262,9 +262,10 @@ set_base_rel_sizes(PlannerInfo *root)
262262
/*
263263
* If parallelism is allowable for this query in general, see whether
264264
* it's allowable for this rel in particular. We have to do this
265-
* before set_rel_size, because that if this is an inheritance parent,
266-
* set_append_rel_size will pass the consider_parallel flag down to
267-
* inheritance children.
265+
* before set_rel_size(), because (a) if this rel is an inheritance
266+
* parent, set_append_rel_size() will use and perhaps change the rel's
267+
* consider_parallel flag, and (b) for some RTE types, set_rel_size()
268+
* goes ahead and makes paths immediately.
268269
*/
269270
if (root->glob->parallelModeOK)
270271
set_rel_consider_parallel(root, rel, rte);
@@ -494,18 +495,24 @@ set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
494495

495496
/*
496497
* If this relation could possibly be scanned from within a worker, then set
497-
* the consider_parallel flag. The flag has previously been initialized to
498-
* false, so we just bail out if it becomes clear that we can't safely set it.
498+
* its consider_parallel flag.
499499
*/
500500
static void
501501
set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
502502
RangeTblEntry *rte)
503503
{
504+
/*
505+
* The flag has previously been initialized to false, so we can just
506+
* return if it becomes clear that we can't safely set it.
507+
*/
508+
Assert(!rel->consider_parallel);
509+
504510
/* Don't call this if parallelism is disallowed for the entire query. */
505511
Assert(root->glob->parallelModeOK);
506512

507-
/* Don't call this for non-baserels. */
508-
Assert(rel->reloptkind == RELOPT_BASEREL);
513+
/* This should only be called for baserels and appendrel children. */
514+
Assert(rel->reloptkind == RELOPT_BASEREL ||
515+
rel->reloptkind == RELOPT_OTHER_MEMBER_REL);
509516

510517
/* Assorted checks based on rtekind. */
511518
switch (rte->rtekind)
@@ -556,6 +563,13 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
556563
if (!rel->fdwroutine->IsForeignScanParallelSafe(root, rel, rte))
557564
return;
558565
}
566+
567+
/*
568+
* There are additional considerations for appendrels, which we'll
569+
* deal with in set_append_rel_size and set_append_rel_pathlist.
570+
* For now, just set consider_parallel based on the rel's own
571+
* quals and targetlist.
572+
*/
559573
break;
560574

561575
case RTE_SUBQUERY:
@@ -607,8 +621,9 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
607621
* give up on parallelizing access to this relation. We could consider
608622
* instead postponing application of the restricted quals until we're
609623
* above all the parallelism in the plan tree, but it's not clear that
610-
* this would be a win in very many cases, and it might be tricky to make
611-
* outer join clauses work correctly.
624+
* that would be a win in very many cases, and it might be tricky to make
625+
* outer join clauses work correctly. It would likely break equivalence
626+
* classes, too.
612627
*/
613628
if (has_parallel_hazard((Node *) rel->baserestrictinfo, false))
614629
return;
@@ -965,9 +980,6 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
965980
continue;
966981
}
967982

968-
/* Copy consider_parallel flag from parent. */
969-
childrel->consider_parallel = rel->consider_parallel;
970-
971983
/*
972984
* CE failed, so finish copying/modifying targetlist and join quals.
973985
*
@@ -1007,6 +1019,16 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
10071019
* otherrels. So we just leave the child's attr_needed empty.
10081020
*/
10091021

1022+
/*
1023+
* If parallelism is allowable for this query in general, see whether
1024+
* it's allowable for this childrel in particular. But if we've
1025+
* already decided the appendrel is not parallel-safe as a whole,
1026+
* there's no point in considering parallelism for this child. For
1027+
* consistency, do this before calling set_rel_size() for the child.
1028+
*/
1029+
if (root->glob->parallelModeOK && rel->consider_parallel)
1030+
set_rel_consider_parallel(root, childrel, childRTE);
1031+
10101032
/*
10111033
* Compute the child's size.
10121034
*/
@@ -1023,6 +1045,18 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
10231045
/* We have at least one live child. */
10241046
has_live_children = true;
10251047

1048+
/*
1049+
* If any live child is not parallel-safe, treat the whole appendrel
1050+
* as not parallel-safe. In future we might be able to generate plans
1051+
* in which some children are farmed out to workers while others are
1052+
* not; but we don't have that today, so it's a waste to consider
1053+
* partial paths anywhere in the appendrel unless it's all safe.
1054+
* (Child rels visited before this one will be unmarked in
1055+
* set_append_rel_pathlist().)
1056+
*/
1057+
if (!childrel->consider_parallel)
1058+
rel->consider_parallel = false;
1059+
10261060
/*
10271061
* Accumulate size information from each live child.
10281062
*/
@@ -1139,6 +1173,15 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
11391173
childRTE = root->simple_rte_array[childRTindex];
11401174
childrel = root->simple_rel_array[childRTindex];
11411175

1176+
/*
1177+
* If set_append_rel_size() decided the parent appendrel was
1178+
* parallel-unsafe at some point after visiting this child rel, we
1179+
* need to propagate the unsafety marking down to the child, so that
1180+
* we don't generate useless partial paths for it.
1181+
*/
1182+
if (!rel->consider_parallel)
1183+
childrel->consider_parallel = false;
1184+
11421185
/*
11431186
* Compute the child's access paths.
11441187
*/

0 commit comments

Comments
 (0)