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

Add a new upper planner relation for partially-aggregated results.

Up until now, we've abused grouped_rel->partial_pathlist as a place to
store partial paths that have been partially aggregate, but that's
really not correct, because a partial path for a relation is supposed
to be one which produces the correct results with the addition of only
a Gather or Gather Merge node, and these paths also require a Finalize
Aggregate step.  Instead, add a new partially_group_rel which can hold
either partial paths (which need to be gathered and then have
aggregation finalized) or non-partial paths (which only need to have
aggregation finalized).  This allows us to reuse generate_gather_paths
for partially_grouped_rel instead of writing new code, so that this
patch actually basically no net new code while making things cleaner,
simplifying things for pending patches for partition-wise aggregate.

Robert Haas and Jeevan Chalke.  The larger patch series of which this
patch is a part was also reviewed and tested by Antonin Houska,
Rajkumar Raghuwanshi, David Rowley, Dilip Kumar, Konstantin Knizhnik,
Pascal Legrand, Rafia Sabih, and me.

Discussion: http://postgr.es/m/CA+TgmobrzFYS3+U8a_BCy3-hOvh5UyJbC18rEcYehxhpw5=ETA@mail.gmail.com
Discussion: http://postgr.es/m/CA+TgmoZyQEjdBNuoG9-wC5GQ5GrO4544Myo13dVptvx+uLg9uQ@mail.gmail.com
parent 5b570d77
...@@ -998,6 +998,7 @@ considered useful for each step. Currently, we may create these types of ...@@ -998,6 +998,7 @@ considered useful for each step. Currently, we may create these types of
additional RelOptInfos during upper-level planning: additional RelOptInfos during upper-level planning:
UPPERREL_SETOP result of UNION/INTERSECT/EXCEPT, if any UPPERREL_SETOP result of UNION/INTERSECT/EXCEPT, if any
UPPERREL_PARTIAL_GROUP_AGG result of partial grouping/aggregation, if any
UPPERREL_GROUP_AGG result of grouping/aggregation, if any UPPERREL_GROUP_AGG result of grouping/aggregation, if any
UPPERREL_WINDOW result of window functions, if any UPPERREL_WINDOW result of window functions, if any
UPPERREL_DISTINCT result of "SELECT DISTINCT", if any UPPERREL_DISTINCT result of "SELECT DISTINCT", if any
......
...@@ -268,7 +268,7 @@ merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, bool force) ...@@ -268,7 +268,7 @@ merge_clump(PlannerInfo *root, List *clumps, Clump *new_clump, bool force)
generate_partitionwise_join_paths(root, joinrel); generate_partitionwise_join_paths(root, joinrel);
/* Create GatherPaths for any useful partial paths for rel */ /* Create GatherPaths for any useful partial paths for rel */
generate_gather_paths(root, joinrel); generate_gather_paths(root, joinrel, false);
/* Find and save the cheapest paths for this joinrel */ /* Find and save the cheapest paths for this joinrel */
set_cheapest(joinrel); set_cheapest(joinrel);
......
...@@ -488,7 +488,7 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel, ...@@ -488,7 +488,7 @@ set_rel_pathlist(PlannerInfo *root, RelOptInfo *rel,
* we'll consider gathering partial paths for the parent appendrel.) * we'll consider gathering partial paths for the parent appendrel.)
*/ */
if (rel->reloptkind == RELOPT_BASEREL) if (rel->reloptkind == RELOPT_BASEREL)
generate_gather_paths(root, rel); generate_gather_paths(root, rel, false);
/* /*
* Allow a plugin to editorialize on the set of Paths for this base * Allow a plugin to editorialize on the set of Paths for this base
...@@ -2444,27 +2444,42 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte) ...@@ -2444,27 +2444,42 @@ set_worktable_pathlist(PlannerInfo *root, RelOptInfo *rel, RangeTblEntry *rte)
* This must not be called until after we're done creating all partial paths * 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 * for the specified relation. (Otherwise, add_partial_path might delete a
* path that some GatherPath or GatherMergePath has a reference to.) * path that some GatherPath or GatherMergePath has a reference to.)
*
* If we're generating paths for a scan or join relation, override_rows will
* be false, and we'll just use the relation's size estimate. When we're
* being called for a partially-grouped path, though, we need to override
* the rowcount estimate. (It's not clear that the particular value we're
* using here is actually best, but the underlying rel has no estimate so
* we must do something.)
*/ */
void void
generate_gather_paths(PlannerInfo *root, RelOptInfo *rel) generate_gather_paths(PlannerInfo *root, RelOptInfo *rel, bool override_rows)
{ {
Path *cheapest_partial_path; Path *cheapest_partial_path;
Path *simple_gather_path; Path *simple_gather_path;
ListCell *lc; ListCell *lc;
double rows;
double *rowsp = NULL;
/* If there are no partial paths, there's nothing to do here. */ /* If there are no partial paths, there's nothing to do here. */
if (rel->partial_pathlist == NIL) if (rel->partial_pathlist == NIL)
return; return;
/* Should we override the rel's rowcount estimate? */
if (override_rows)
rowsp = &rows;
/* /*
* The output of Gather is always unsorted, so there's only one partial * The output of Gather is always unsorted, so there's only one partial
* path of interest: the cheapest one. That will be the one at the front * 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. * of partial_pathlist because of the way add_partial_path works.
*/ */
cheapest_partial_path = linitial(rel->partial_pathlist); cheapest_partial_path = linitial(rel->partial_pathlist);
rows =
cheapest_partial_path->rows * cheapest_partial_path->parallel_workers;
simple_gather_path = (Path *) simple_gather_path = (Path *)
create_gather_path(root, rel, cheapest_partial_path, rel->reltarget, create_gather_path(root, rel, cheapest_partial_path, rel->reltarget,
NULL, NULL); NULL, rowsp);
add_path(rel, simple_gather_path); add_path(rel, simple_gather_path);
/* /*
...@@ -2479,8 +2494,9 @@ generate_gather_paths(PlannerInfo *root, RelOptInfo *rel) ...@@ -2479,8 +2494,9 @@ generate_gather_paths(PlannerInfo *root, RelOptInfo *rel)
if (subpath->pathkeys == NIL) if (subpath->pathkeys == NIL)
continue; continue;
rows = subpath->rows * subpath->parallel_workers;
path = create_gather_merge_path(root, rel, subpath, rel->reltarget, path = create_gather_merge_path(root, rel, subpath, rel->reltarget,
subpath->pathkeys, NULL, NULL); subpath->pathkeys, NULL, rowsp);
add_path(rel, &path->path); add_path(rel, &path->path);
} }
} }
...@@ -2653,7 +2669,7 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels) ...@@ -2653,7 +2669,7 @@ standard_join_search(PlannerInfo *root, int levels_needed, List *initial_rels)
generate_partitionwise_join_paths(root, rel); generate_partitionwise_join_paths(root, rel);
/* Create GatherPaths for any useful partial paths for rel */ /* Create GatherPaths for any useful partial paths for rel */
generate_gather_paths(root, rel); generate_gather_paths(root, rel, false);
/* Find and save the cheapest paths for this rel */ /* Find and save the cheapest paths for this rel */
set_cheapest(rel); set_cheapest(rel);
......
This diff is collapsed.
...@@ -71,6 +71,8 @@ typedef struct AggClauseCosts ...@@ -71,6 +71,8 @@ typedef struct AggClauseCosts
typedef enum UpperRelationKind typedef enum UpperRelationKind
{ {
UPPERREL_SETOP, /* result of UNION/INTERSECT/EXCEPT, if any */ UPPERREL_SETOP, /* result of UNION/INTERSECT/EXCEPT, if any */
UPPERREL_PARTIAL_GROUP_AGG, /* result of partial grouping/aggregation, if
* any */
UPPERREL_GROUP_AGG, /* result of grouping/aggregation, if any */ UPPERREL_GROUP_AGG, /* result of grouping/aggregation, if any */
UPPERREL_WINDOW, /* result of window functions, if any */ UPPERREL_WINDOW, /* result of window functions, if any */
UPPERREL_DISTINCT, /* result of "SELECT DISTINCT", if any */ UPPERREL_DISTINCT, /* result of "SELECT DISTINCT", if any */
......
...@@ -53,7 +53,8 @@ extern void set_dummy_rel_pathlist(RelOptInfo *rel); ...@@ -53,7 +53,8 @@ extern void set_dummy_rel_pathlist(RelOptInfo *rel);
extern RelOptInfo *standard_join_search(PlannerInfo *root, int levels_needed, extern RelOptInfo *standard_join_search(PlannerInfo *root, int levels_needed,
List *initial_rels); List *initial_rels);
extern void generate_gather_paths(PlannerInfo *root, RelOptInfo *rel); extern void generate_gather_paths(PlannerInfo *root, RelOptInfo *rel,
bool override_rows);
extern int compute_parallel_worker(RelOptInfo *rel, double heap_pages, extern int compute_parallel_worker(RelOptInfo *rel, double heap_pages,
double index_pages, int max_workers); double index_pages, int max_workers);
extern void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *rel, extern void create_partial_bitmap_paths(PlannerInfo *root, RelOptInfo *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