diff options
Diffstat (limited to 'src/backend/optimizer/path/allpaths.c')
-rw-r--r-- | src/backend/optimizer/path/allpaths.c | 50 |
1 files changed, 30 insertions, 20 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 17c1edd9703..5246260e12a 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -73,7 +73,7 @@ static void set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, Index rti, RangeTblEntry *rte); static void set_plain_rel_size(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); -static void create_parallel_paths(PlannerInfo *root, RelOptInfo *rel); +static void create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel); static void set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte); static bool function_rte_parallel_ok(RangeTblEntry *rte); @@ -448,6 +448,16 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, } /* + * If this is a baserel, consider gathering any partial paths we may have + * created for it. (If we tried to gather inheritance children, we could + * end up with a very large number of gather nodes, each trying to grab + * its own pool of workers, so don't do this for otherrels. Instead, + * we'll consider gathering partial paths for the parent appendrel.) + */ + if (rel->reloptkind == RELOPT_BASEREL) + generate_gather_paths(root, rel); + + /* * Allow a plugin to editorialize on the set of Paths for this base * relation. It could add new paths (such as CustomPaths) by calling * add_path(), or delete or modify paths added by the core code. @@ -643,7 +653,7 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) /* If appropriate, consider parallel sequential scan */ if (rel->consider_parallel && required_outer == NULL) - create_parallel_paths(root, rel); + create_plain_partial_paths(root, rel); /* Consider index scans */ create_index_paths(root, rel); @@ -653,11 +663,11 @@ set_plain_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) } /* - * create_parallel_paths - * Build parallel access paths for a plain relation + * create_plain_partial_paths + * Build partial access paths for parallel scan of a plain relation */ static void -create_parallel_paths(PlannerInfo *root, RelOptInfo *rel) +create_plain_partial_paths(PlannerInfo *root, RelOptInfo *rel) { int parallel_degree = 1; @@ -712,16 +722,6 @@ create_parallel_paths(PlannerInfo *root, RelOptInfo *rel) /* Add an unordered partial path based on a parallel sequential scan. */ add_partial_path(rel, create_seqscan_path(root, rel, NULL, parallel_degree)); - - /* - * If this is a baserel, consider gathering any partial paths we may have - * just created. If we gathered an inheritance child, we could end up - * with a very large number of gather nodes, each trying to grab its own - * pool of workers, so don't do this in that case. Instead, we'll - * consider gathering partial paths for the appendrel. - */ - if (rel->reloptkind == RELOPT_BASEREL) - generate_gather_paths(root, rel); } /* @@ -1262,9 +1262,6 @@ set_append_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, appendpath = create_append_path(rel, partial_subpaths, NULL, parallel_degree); add_partial_path(rel, (Path *) appendpath); - - /* Consider gathering it. */ - generate_gather_paths(root, rel); } /* @@ -1970,6 +1967,10 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) * generate_gather_paths * Generate parallel access paths for a relation by pushing a Gather on * top of a partial path. + * + * This must not be called until after we're done creating all partial paths + * for the specified relation. (Otherwise, add_partial_path might delete a + * path that some GatherPath has a reference to.) */ void generate_gather_paths(PlannerInfo *root, RelOptInfo *rel) @@ -1983,7 +1984,9 @@ generate_gather_paths(PlannerInfo *root, RelOptInfo *rel) /* * The output of Gather is currently always unsorted, so there's only one - * partial path of interest: the cheapest one. + * partial path of interest: the cheapest one. That will be the one at + * the front of partial_pathlist because of the way add_partial_path + * works. * * Eventually, we should have a Gather Merge operation that can merge * multiple tuple streams together while preserving their ordering. We @@ -2148,12 +2151,19 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels) join_search_one_level(root, lev); /* - * Do cleanup work on each just-processed rel. + * Run generate_gather_paths() for each just-processed joinrel. We + * could not do this earlier because both regular and partial paths + * can get added to a particular joinrel at multiple times within + * join_search_one_level. After that, we're done creating paths + * for the joinrel, so run set_cheapest(). */ foreach(lc, root->join_rel_level[lev]) { rel = (RelOptInfo *) lfirst(lc); + /* Create GatherPaths for any useful partial paths for rel */ + generate_gather_paths(root, rel); + /* Find and save the cheapest paths for this rel */ set_cheapest(rel); |