0001-Remove-loop-from-0-to-1.patch
application/octet-stream
Filename: 0001-Remove-loop-from-0-to-1.patch
Type: application/octet-stream
Part: 2
Patch
Format: format-patch
Series: patch 0001
Subject: Remove loop from 0 to 1.
| File | + | − |
|---|---|---|
| src/backend/optimizer/plan/planner.c | 171 | 118 |
From 54a8a61abb3c629196e6e9a778f8527103df26c2 Mon Sep 17 00:00:00 2001
From: Robert Haas <rhaas@postgresql.org>
Date: Tue, 20 Mar 2018 14:12:58 -0400
Subject: [PATCH 1/3] Remove loop from 0 to 1.
---
src/backend/optimizer/plan/planner.c | 289 +++++++++++++++++++++--------------
1 file changed, 171 insertions(+), 118 deletions(-)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 4c11d84fd6..c05182d479 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -6378,14 +6378,32 @@ create_partial_grouping_paths(PlannerInfo *root,
RelOptInfo *partially_grouped_rel;
AggClauseCosts *agg_partial_costs = &extra->agg_partial_costs;
AggClauseCosts *agg_final_costs = &extra->agg_final_costs;
- Path *cheapest_path;
- Size hashaggtablesize;
+ Path *cheapest_partial_path = NULL;
+ Path *cheapest_total_path = NULL;
double dNumPartialGroups = 0;
+ double dNumPartialPartialGroups = 0;
ListCell *lc;
bool can_hash = (extra->flags & GROUPING_CAN_USE_HASH) != 0;
bool can_sort = (extra->flags & GROUPING_CAN_USE_SORT) != 0;
- bool use_partial_pathlist;
- int i;
+
+ /*
+ * Consider whether we should generate partially aggregated non-partial
+ * paths. We can only do this if we have a non-partial path, and in
+ * addition the caller must have requested it by setting
+ * extra->is_partial_aggregation or
+ * extra->perform_partial_partitionwise_aggregation.
+ */
+ if (input_rel->pathlist != NIL && (extra->is_partial_aggregation ||
+ extra->perform_partial_partitionwise_aggregation))
+ cheapest_total_path = input_rel->cheapest_total_path;
+
+ /*
+ * If parallelism is possible for grouped_rel, then we should consider
+ * generating partially-grouped partial paths. However, if the input rel
+ * has no partial paths, then we can't.
+ */
+ if (grouped_rel->consider_parallel && input_rel->partial_pathlist != NIL)
+ cheapest_partial_path = linitial(input_rel->partial_pathlist);
/*
* Build a new upper relation to represent the result of partially
@@ -6443,137 +6461,172 @@ create_partial_grouping_paths(PlannerInfo *root,
extra->partial_costs_set = true;
}
- /*
- * We loop twice, one to generate paths for partial_pathlist when parallel
- * paths are possible and second time for generating paths in pathlist when
- * we need partially aggregated results for the partitionwise grouping
- * and/or aggregation.
- */
- use_partial_pathlist = true;
- for (i = 0; i < 2; i++)
+ /* Estimate number of partial groups. */
+ if (cheapest_total_path != NULL)
+ dNumPartialGroups =
+ get_number_of_groups(root,
+ cheapest_total_path->rows,
+ gd,
+ extra->targetList);
+ if (cheapest_partial_path != NULL)
+ dNumPartialPartialGroups =
+ get_number_of_groups(root,
+ cheapest_partial_path->rows,
+ gd,
+ extra->targetList);
+
+ if (can_sort && cheapest_total_path != NULL)
{
- if (use_partial_pathlist && !(grouped_rel->consider_parallel &&
- input_rel->partial_pathlist != NIL &&
- (extra->flags & GROUPING_CAN_PARTIAL_AGG) != 0))
- {
- /* No parallel paths possible. */
- use_partial_pathlist = false;
- continue;
- }
+ /* This should have been checked previously */
+ Assert(parse->hasAggs || parse->groupClause);
- if (!use_partial_pathlist && !extra->is_partial_aggregation)
+ /*
+ * Use any available suitably-sorted path as input, and also consider
+ * sorting the cheapest partial path.
+ */
+ foreach(lc, input_rel->pathlist)
{
- /* No partial partitiowise aggregation possible. */
- continue;
- }
+ Path *path = (Path *) lfirst(lc);
+ bool is_sorted;
- /* Get either total or partial cheapest path */
- cheapest_path = use_partial_pathlist ? linitial(input_rel->partial_pathlist) :
- input_rel->cheapest_total_path;
+ is_sorted = pathkeys_contained_in(root->group_pathkeys,
+ path->pathkeys);
+ if (path == cheapest_total_path || is_sorted)
+ {
+ /* Sort the cheapest partial path, if it isn't already */
+ if (!is_sorted)
+ path = (Path *) create_sort_path(root,
+ partially_grouped_rel,
+ path,
+ root->group_pathkeys,
+ -1.0);
- /* Estimate number of partial groups. */
- dNumPartialGroups = get_number_of_groups(root,
- cheapest_path->rows,
- gd,
- extra->targetList);
+ if (parse->hasAggs)
+ add_path(partially_grouped_rel, (Path *)
+ create_agg_path(root,
+ partially_grouped_rel,
+ path,
+ partially_grouped_rel->reltarget,
+ parse->groupClause ? AGG_SORTED : AGG_PLAIN,
+ AGGSPLIT_INITIAL_SERIAL,
+ parse->groupClause,
+ NIL,
+ agg_partial_costs,
+ dNumPartialGroups));
+ else
+ add_path(partially_grouped_rel, (Path *)
+ create_group_path(root,
+ partially_grouped_rel,
+ path,
+ parse->groupClause,
+ NIL,
+ dNumPartialGroups));
+ }
+ }
+ }
- if (can_sort)
+ if (can_sort && cheapest_partial_path != NULL)
+ {
+ /* Similar to above logic, but for partial paths. */
+ foreach(lc, input_rel->partial_pathlist)
{
- List *pathlist;
-
- /* This should have been checked previously */
- Assert(parse->hasAggs || parse->groupClause);
-
- /* Get appropriate pathlist */
- pathlist = use_partial_pathlist ? input_rel->partial_pathlist :
- input_rel->pathlist;
+ Path *path = (Path *) lfirst(lc);
+ bool is_sorted;
- /*
- * Use any available suitably-sorted path as input, and also
- * consider sorting the cheapest path.
- */
- foreach(lc, pathlist)
+ is_sorted = pathkeys_contained_in(root->group_pathkeys,
+ path->pathkeys);
+ if (path == cheapest_partial_path || is_sorted)
{
- Path *path = (Path *) lfirst(lc);
- bool is_sorted;
- Path *gpath;
+ /* Sort the cheapest partial path, if it isn't already */
+ if (!is_sorted)
+ path = (Path *) create_sort_path(root,
+ partially_grouped_rel,
+ path,
+ root->group_pathkeys,
+ -1.0);
- is_sorted = pathkeys_contained_in(root->group_pathkeys,
- path->pathkeys);
- if (path == cheapest_path || is_sorted)
- {
- /* Sort the cheapest path, if it isn't already */
- if (!is_sorted)
- path = (Path *) create_sort_path(root,
- partially_grouped_rel,
- path,
- root->group_pathkeys,
- -1.0);
-
- if (parse->hasAggs)
- gpath = (Path *) create_agg_path(root,
- partially_grouped_rel,
- path,
- partially_grouped_rel->reltarget,
- parse->groupClause ? AGG_SORTED : AGG_PLAIN,
- AGGSPLIT_INITIAL_SERIAL,
- parse->groupClause,
- NIL,
- agg_partial_costs,
- dNumPartialGroups);
- else
- gpath = (Path *) create_group_path(root,
- partially_grouped_rel,
- path,
- parse->groupClause,
- NIL,
- dNumPartialGroups);
-
- if (use_partial_pathlist)
- add_partial_path(partially_grouped_rel, gpath);
- else
- add_path(partially_grouped_rel, gpath);
- }
+ if (parse->hasAggs)
+ add_partial_path(partially_grouped_rel, (Path *)
+ create_agg_path(root,
+ partially_grouped_rel,
+ path,
+ partially_grouped_rel->reltarget,
+ parse->groupClause ? AGG_SORTED : AGG_PLAIN,
+ AGGSPLIT_INITIAL_SERIAL,
+ parse->groupClause,
+ NIL,
+ agg_partial_costs,
+ dNumPartialPartialGroups));
+ else
+ add_partial_path(partially_grouped_rel, (Path *)
+ create_group_path(root,
+ partially_grouped_rel,
+ path,
+ parse->groupClause,
+ NIL,
+ dNumPartialPartialGroups));
}
}
+ }
- if (can_hash)
- {
- /* Checked above */
- Assert(parse->hasAggs || parse->groupClause);
+ if (can_hash && cheapest_total_path != NULL)
+ {
+ Size hashaggtablesize;
- hashaggtablesize =
- estimate_hashagg_tablesize(cheapest_path,
- agg_partial_costs,
- dNumPartialGroups);
+ /* Checked above */
+ Assert(parse->hasAggs || parse->groupClause);
- /*
- * Tentatively produce a partial HashAgg Path, depending on if it
- * looks as if the hash table will fit in work_mem.
- */
- if (hashaggtablesize < work_mem * 1024L)
- {
- Path *gpath;
-
- gpath = (Path *) create_agg_path(root,
- partially_grouped_rel,
- cheapest_path,
- partially_grouped_rel->reltarget,
- AGG_HASHED,
- AGGSPLIT_INITIAL_SERIAL,
- parse->groupClause,
- NIL,
- agg_partial_costs,
- dNumPartialGroups);
-
- if (use_partial_pathlist)
- add_partial_path(partially_grouped_rel, gpath);
- else
- add_path(partially_grouped_rel, gpath);
- }
+ hashaggtablesize =
+ estimate_hashagg_tablesize(cheapest_total_path,
+ agg_partial_costs,
+ dNumPartialGroups);
+
+ /*
+ * Tentatively produce a partial HashAgg Path, depending on if it
+ * looks as if the hash table will fit in work_mem.
+ */
+ if (hashaggtablesize < work_mem * 1024L &&
+ cheapest_total_path != NULL)
+ {
+ add_path(partially_grouped_rel, (Path *)
+ create_agg_path(root,
+ partially_grouped_rel,
+ cheapest_total_path,
+ partially_grouped_rel->reltarget,
+ AGG_HASHED,
+ AGGSPLIT_INITIAL_SERIAL,
+ parse->groupClause,
+ NIL,
+ agg_partial_costs,
+ dNumPartialGroups));
}
+ }
+
+ if (can_hash && cheapest_partial_path != NULL)
+ {
+ Size hashaggtablesize;
+
+ hashaggtablesize =
+ estimate_hashagg_tablesize(cheapest_partial_path,
+ agg_partial_costs,
+ dNumPartialPartialGroups);
- use_partial_pathlist = false;
+ /* Do the same for partial paths. */
+ if (hashaggtablesize < work_mem * 1024L &&
+ cheapest_partial_path != NULL)
+ {
+ add_partial_path(partially_grouped_rel, (Path *)
+ create_agg_path(root,
+ partially_grouped_rel,
+ cheapest_partial_path,
+ partially_grouped_rel->reltarget,
+ AGG_HASHED,
+ AGGSPLIT_INITIAL_SERIAL,
+ parse->groupClause,
+ NIL,
+ agg_partial_costs,
+ dNumPartialPartialGroups));
+ }
}
/*
--
2.14.3 (Apple Git-98)