Commit 3f90ec85 authored by Robert Haas's avatar Robert Haas

Postpone generate_gather_paths for topmost scan/join rel.

Don't call generate_gather_paths for the topmost scan/join relation
when it is initially populated with paths.  Instead, do the work in
grouping_planner.  By itself, this gains nothing; in fact it loses
slightly because we end up calling set_cheapest() for the topmost
scan/join rel twice rather than once.  However, it paves the way for
a future commit which will postpone generate_gather_paths for the
topmost scan/join relation even further, allowing more accurate
costing of parallel paths.

Amit Kapila and Robert Haas.  Earlier versions of this patch (which
different substantially) were reviewed by Dilip Kumar, Amit
Khandekar, Marina Polyakova, and Ashutosh Bapat.
parent d7c19e62
......@@ -40,7 +40,7 @@ typedef struct
} Clump;
static List *merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump,
bool force);
int num_gene, bool force);
static bool desirable_join(PlannerInfo *root,
RelOptInfo *outer_rel, RelOptInfo *inner_rel);
......@@ -196,7 +196,7 @@ gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
cur_clump->size = 1;
/* Merge it into the clumps list, using only desirable joins */
clumps = merge_clump(root, clumps, cur_clump, false);
clumps = merge_clump(root, clumps, cur_clump, num_gene, false);
}
if (list_length(clumps) > 1)
......@@ -210,7 +210,7 @@ gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
{
Clump *clump = (Clump *) lfirst(lc);
fclumps = merge_clump(root, fclumps, clump, true);
fclumps = merge_clump(root, fclumps, clump, num_gene, true);
}
clumps = fclumps;
}
......@@ -235,7 +235,8 @@ gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
* "desirable" joins.
*/
static List *
merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, bool force)
merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, int num_gene,
bool force)
{
ListCell *prev;
ListCell *lc;
......@@ -267,8 +268,14 @@ merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, bool force)
/* Create paths for partitionwise joins. */
generate_partitionwise_join_paths(root, joinrel);
/* Create GatherPaths for any useful partial paths for rel */
generate_gather_paths(root, joinrel, false);
/*
* Except for the topmost scan/join rel, consider gathering
* partial paths. We'll do the same for the topmost scan/join
* rel once we know the final targetlist (see
* grouping_planner).
*/
if (old_clump->size + new_clump->size < num_gene)
generate_gather_paths(root, joinrel, false);
/* Find and save the cheapest paths for this joinrel */
set_cheapest(joinrel);
......@@ -286,7 +293,7 @@ merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, bool force)
* others. When no further merge is possible, we'll reinsert
* it into the list.
*/
return merge_clump(root, clumps, old_clump, force);
return merge_clump(root, clumps, old_clump, num_gene, force);
}
}
prev = lc;
......
......@@ -479,13 +479,20 @@ 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
* If this is a baserel, we should normally consider gathering any partial
* paths we may have created for it.
*
* However, if this is an inheritance child, skip it. Otherwise, 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.)
* its own pool of workers. Instead, we'll consider gathering partial
* paths for the parent appendrel.
*
* Also, if this is the topmost scan/join rel (that is, the only baserel),
* we postpone this until the final scan/join targelist is available (see
* grouping_planner).
*/
if (rel->reloptkind == RELOPT_BASEREL)
if (rel->reloptkind == RELOPT_BASEREL &&
bms_membership(root->all_baserels) != BMS_SINGLETON)
generate_gather_paths(root, rel, false);
/*
......@@ -2699,8 +2706,13 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
/* Create paths for partitionwise joins. */
generate_partitionwise_join_paths(root, rel);
/* Create GatherPaths for any useful partial paths for rel */
generate_gather_paths(root, rel, false);
/*
* Except for the topmost scan/join rel, consider gathering
* partial paths. We'll do the same for the topmost scan/join rel
* once we know the final targetlist (see grouping_planner).
*/
if (lev < levels_needed)
generate_gather_paths(root, rel, false);
/* Find and save the cheapest paths for this rel */
set_cheapest(rel);
......
......@@ -1974,6 +1974,15 @@ grouping_planner(PlannerInfo *root, bool inheritance_update,
scanjoin_targets = scanjoin_targets_contain_srfs = NIL;
}
/*
* Generate Gather or Gather Merge paths for the topmost scan/join
* relation. Once that's done, we must re-determine which paths are
* cheapest. (The previously-cheapest path might even have been
* pfree'd!)
*/
generate_gather_paths(root, current_rel, false);
set_cheapest(current_rel);
/*
* Forcibly apply SRF-free scan/join target to all the Paths for the
* scan/join rel.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment