diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 2e4b670..57fd06e 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -242,6 +242,37 @@ set_base_rel_sizes(PlannerInfo *root) { Index rti; + /* + * If parallel query is a possibility, tentatively set consider_parallel + * for those base and "other member" relations for which it seems + * plausible. We must do this before set_rel_size() is called for + * inheritance relations, because part of it's job is to clear the + * consider_parallel flag if any child is not so marked. + */ + if (root->glob->parallelModeOK) + { + for (rti = 1; rti < root->simple_rel_array_size; rti++) + { + RelOptInfo *rel = root->simple_rel_array[rti]; + RangeTblEntry *rte; + + /* there may be empty slots corresponding to non-baserel RTEs */ + if (rel == NULL) + continue; + if (rel->reloptkind != RELOPT_BASEREL && + rel->reloptkind != RELOPT_OTHER_MEMBER_REL) + continue; + Assert(rel->relid == rti); /* sanity check on array */ + + rte = root->simple_rte_array[rti]; + set_rel_consider_parallel(root, rel, rte); + } + } + + /* + * Now set size estimates, possibly clearing consider_parallel for some + * parent rels as a side effect. + */ for (rti = 1; rti < root->simple_rel_array_size; rti++) { RelOptInfo *rel = root->simple_rel_array[rti]; @@ -259,16 +290,6 @@ set_base_rel_sizes(PlannerInfo *root) rte = root->simple_rte_array[rti]; - /* - * If parallelism is allowable for this query in general, see whether - * it's allowable for this rel in particular. We have to do this - * before set_rel_size, because that if this is an inheritance parent, - * set_append_rel_size will pass the consider_parallel flag down to - * inheritance children. - */ - if (root->glob->parallelModeOK) - set_rel_consider_parallel(root, rel, rte); - set_rel_size(root, rel, rti, rte); } } @@ -504,8 +525,9 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel, /* Don't call this if parallelism is disallowed for the entire query. */ Assert(root->glob->parallelModeOK); - /* Don't call this for non-baserels. */ - Assert(rel->reloptkind == RELOPT_BASEREL); + /* This should only be called for base or "other member" relations. */ + Assert(rel->reloptkind == RELOPT_BASEREL || + rel->reloptkind == RELOPT_OTHER_MEMBER_REL); /* Assorted checks based on rtekind. */ switch (rte->rtekind) @@ -562,15 +584,12 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel, case RTE_SUBQUERY: /* - * Subplans currently aren't passed to workers. Even if they - * were, the subplan might be using parallelism internally, and we - * can't support nested Gather nodes at present. Finally, we - * don't have a good way of knowing whether the subplan involves - * any parallel-restricted operations. It would be nice to relax - * this restriction some day, but it's going to take a fair amount - * of work. + * There's no intrinsic problem with scanning a subquery from a + * parallel worker. If the subquery doesn't happen to have any + * parallel-safe paths, then flagging it as consider_parallel + * won't help, but that's true for plain tables, too. */ - return; + break; case RTE_JOIN: /* Shouldn't happen; we're only considering baserels here. */ @@ -966,8 +985,9 @@ set_append_rel_size(PlannerInfo *root, RelOptInfo *rel, continue; } - /* Copy consider_parallel flag from parent. */ - childrel->consider_parallel = rel->consider_parallel; + /* If any childrel is not parallel-safe, neither is parent. */ + if (!childrel->consider_parallel) + rel->consider_parallel = false; /* * CE failed, so finish copying/modifying targetlist and join quals. @@ -1141,6 +1161,17 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, childrel = root->simple_rel_array[childRTindex]; /* + * If the parent isn't eligible for parallelism, there's no point + * in considering it for the children. (This might change someday + * if we have a way to build an Append plan where some of the child + * plans are forced to run in the parent and others can run in any + * process, but for now there's no point in expending cycles building + * childrel paths we can't use.) + */ + if (!rel->consider_parallel) + childrel->consider_parallel = false; + + /* * Compute the child's access paths. */ set_rel_pathlist(root, childrel, childRTindex, childRTE);