@@ -165,8 +165,8 @@ make_one_rel(PlannerInfo *root, List *joinlist)
165
165
set_base_rel_consider_startup (root );
166
166
167
167
/*
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 .
170
170
*/
171
171
set_base_rel_sizes (root );
172
172
set_base_rel_pathlists (root );
@@ -234,7 +234,7 @@ set_base_rel_consider_startup(PlannerInfo *root)
234
234
*
235
235
* We do this in a separate pass over the base rels so that rowcount
236
236
* 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
238
238
* generate paths.
239
239
*/
240
240
static void
@@ -262,9 +262,10 @@ set_base_rel_sizes(PlannerInfo *root)
262
262
/*
263
263
* If parallelism is allowable for this query in general, see whether
264
264
* 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.
268
269
*/
269
270
if (root -> glob -> parallelModeOK )
270
271
set_rel_consider_parallel (root , rel , rte );
@@ -494,18 +495,24 @@ set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
494
495
495
496
/*
496
497
* 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.
499
499
*/
500
500
static void
501
501
set_rel_consider_parallel (PlannerInfo * root , RelOptInfo * rel ,
502
502
RangeTblEntry * rte )
503
503
{
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
+
504
510
/* Don't call this if parallelism is disallowed for the entire query. */
505
511
Assert (root -> glob -> parallelModeOK );
506
512
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 );
509
516
510
517
/* Assorted checks based on rtekind. */
511
518
switch (rte -> rtekind )
@@ -556,6 +563,13 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
556
563
if (!rel -> fdwroutine -> IsForeignScanParallelSafe (root , rel , rte ))
557
564
return ;
558
565
}
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
+ */
559
573
break ;
560
574
561
575
case RTE_SUBQUERY :
@@ -607,8 +621,9 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
607
621
* give up on parallelizing access to this relation. We could consider
608
622
* instead postponing application of the restricted quals until we're
609
623
* 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.
612
627
*/
613
628
if (has_parallel_hazard ((Node * ) rel -> baserestrictinfo , false))
614
629
return ;
@@ -965,9 +980,6 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
965
980
continue ;
966
981
}
967
982
968
- /* Copy consider_parallel flag from parent. */
969
- childrel -> consider_parallel = rel -> consider_parallel ;
970
-
971
983
/*
972
984
* CE failed, so finish copying/modifying targetlist and join quals.
973
985
*
@@ -1007,6 +1019,16 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
1007
1019
* otherrels. So we just leave the child's attr_needed empty.
1008
1020
*/
1009
1021
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
+
1010
1032
/*
1011
1033
* Compute the child's size.
1012
1034
*/
@@ -1023,6 +1045,18 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel,
1023
1045
/* We have at least one live child. */
1024
1046
has_live_children = true;
1025
1047
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
+
1026
1060
/*
1027
1061
* Accumulate size information from each live child.
1028
1062
*/
@@ -1139,6 +1173,15 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
1139
1173
childRTE = root -> simple_rte_array [childRTindex ];
1140
1174
childrel = root -> simple_rel_array [childRTindex ];
1141
1175
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
+
1142
1185
/*
1143
1186
* Compute the child's access paths.
1144
1187
*/
0 commit comments