diff options
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 66 |
1 files changed, 25 insertions, 41 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 986d7a52e32..247f7d46252 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -152,7 +152,6 @@ static RelOptInfo *create_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, bool target_parallel_safe, - const AggClauseCosts *agg_costs, grouping_sets_data *gd); static bool is_degenerate_grouping(PlannerInfo *root); static void create_degenerate_grouping_paths(PlannerInfo *root, @@ -228,8 +227,7 @@ static RelOptInfo *create_partial_grouping_paths(PlannerInfo *root, GroupPathExtraData *extra, bool force_rel_creation); static void gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel); -static bool can_partial_agg(PlannerInfo *root, - const AggClauseCosts *agg_costs); +static bool can_partial_agg(PlannerInfo *root); static void apply_scanjoin_target_to_paths(PlannerInfo *root, RelOptInfo *rel, List *scanjoin_targets, @@ -1944,7 +1942,6 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, bool scanjoin_target_parallel_safe; bool scanjoin_target_same_exprs; bool have_grouping; - AggClauseCosts agg_costs; WindowFuncLists *wflists = NULL; List *activeWindows = NIL; grouping_sets_data *gset_data = NULL; @@ -1975,25 +1972,16 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, root->processed_tlist = preprocess_targetlist(root); /* - * Collect statistics about aggregates for estimating costs, and mark - * all the aggregates with resolved aggtranstypes. We must do this - * before slicing and dicing the tlist into various pathtargets, else - * some copies of the Aggref nodes might escape being marked with the - * correct transtypes. - * - * Note: currently, we do not detect duplicate aggregates here. This - * may result in somewhat-overestimated cost, which is fine for our - * purposes since all Paths will get charged the same. But at some - * point we might wish to do that detection in the planner, rather - * than during executor startup. + * Mark all the aggregates with resolved aggtranstypes, and detect + * aggregates that are duplicates or can share transition state. We + * must do this before slicing and dicing the tlist into various + * pathtargets, else some copies of the Aggref nodes might escape + * being marked. */ - MemSet(&agg_costs, 0, sizeof(AggClauseCosts)); if (parse->hasAggs) { - get_agg_clause_costs(root, (Node *) root->processed_tlist, - AGGSPLIT_SIMPLE, &agg_costs); - get_agg_clause_costs(root, parse->havingQual, AGGSPLIT_SIMPLE, - &agg_costs); + preprocess_aggrefs(root, (Node *) root->processed_tlist); + preprocess_aggrefs(root, (Node *) parse->havingQual); } /* @@ -2198,7 +2186,6 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, current_rel, grouping_target, grouping_target_parallel_safe, - &agg_costs, gset_data); /* Fix things up if grouping_target contains SRFs */ if (parse->hasTargetSRFs) @@ -3790,7 +3777,6 @@ get_number_of_groups(PlannerInfo *root, * * input_rel: contains the source-data Paths * target: the pathtarget for the result Paths to compute - * agg_costs: cost info about all aggregates in query (in AGGSPLIT_SIMPLE mode) * gd: grouping sets data including list of grouping sets and their clauses * * Note: all Paths in input_rel are expected to return the target computed @@ -3801,12 +3787,15 @@ create_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, bool target_parallel_safe, - const AggClauseCosts *agg_costs, grouping_sets_data *gd) { Query *parse = root->parse; RelOptInfo *grouped_rel; RelOptInfo *partially_grouped_rel; + AggClauseCosts agg_costs; + + MemSet(&agg_costs, 0, sizeof(AggClauseCosts)); + get_agg_clause_costs(root, AGGSPLIT_SIMPLE, &agg_costs); /* * Create grouping relation to hold fully aggregated grouping and/or @@ -3862,14 +3851,14 @@ create_grouping_paths(PlannerInfo *root, * the other gating conditions, so we want to do it last. */ if ((parse->groupClause != NIL && - agg_costs->numOrderedAggs == 0 && + root->numOrderedAggs == 0 && (gd ? gd->any_hashable : grouping_is_hashable(parse->groupClause)))) flags |= GROUPING_CAN_USE_HASH; /* * Determine whether partial aggregation is possible. */ - if (can_partial_agg(root, agg_costs)) + if (can_partial_agg(root)) flags |= GROUPING_CAN_PARTIAL_AGG; extra.flags = flags; @@ -3890,7 +3879,7 @@ create_grouping_paths(PlannerInfo *root, extra.patype = PARTITIONWISE_AGGREGATE_NONE; create_ordinary_grouping_paths(root, input_rel, grouped_rel, - agg_costs, gd, &extra, + &agg_costs, gd, &extra, &partially_grouped_rel); } @@ -4248,7 +4237,8 @@ consider_groupingsets_paths(PlannerInfo *root, l_start = lnext(gd->rollups, l_start); } - hashsize = estimate_hashagg_tablesize(path, + hashsize = estimate_hashagg_tablesize(root, + path, agg_costs, dNumGroups - exclude_groups); @@ -4382,7 +4372,8 @@ consider_groupingsets_paths(PlannerInfo *root, /* * Account first for space needed for groups we can't sort at all. */ - availspace -= estimate_hashagg_tablesize(path, + availspace -= estimate_hashagg_tablesize(root, + path, agg_costs, gd->dNumHashGroups); @@ -4433,7 +4424,8 @@ consider_groupingsets_paths(PlannerInfo *root, if (rollup->hashable) { - double sz = estimate_hashagg_tablesize(path, + double sz = estimate_hashagg_tablesize(root, + path, agg_costs, rollup->numGroups); @@ -6926,20 +6918,12 @@ create_partial_grouping_paths(PlannerInfo *root, MemSet(agg_final_costs, 0, sizeof(AggClauseCosts)); if (parse->hasAggs) { - List *partial_target_exprs; - /* partial phase */ - partial_target_exprs = partially_grouped_rel->reltarget->exprs; - get_agg_clause_costs(root, (Node *) partial_target_exprs, - AGGSPLIT_INITIAL_SERIAL, + get_agg_clause_costs(root, AGGSPLIT_INITIAL_SERIAL, agg_partial_costs); /* final phase */ - get_agg_clause_costs(root, (Node *) grouped_rel->reltarget->exprs, - AGGSPLIT_FINAL_DESERIAL, - agg_final_costs); - get_agg_clause_costs(root, extra->havingQual, - AGGSPLIT_FINAL_DESERIAL, + get_agg_clause_costs(root, AGGSPLIT_FINAL_DESERIAL, agg_final_costs); } @@ -7324,7 +7308,7 @@ gather_grouping_paths(PlannerInfo *root, RelOptInfo *rel) * Returns true when possible, false otherwise. */ static bool -can_partial_agg(PlannerInfo *root, const AggClauseCosts *agg_costs) +can_partial_agg(PlannerInfo *root) { Query *parse = root->parse; @@ -7341,7 +7325,7 @@ can_partial_agg(PlannerInfo *root, const AggClauseCosts *agg_costs) /* We don't know how to do grouping sets in parallel. */ return false; } - else if (agg_costs->hasNonPartial || agg_costs->hasNonSerial) + else if (root->hasNonPartialAggs || root->hasNonSerialAggs) { /* Insufficient support for partial mode. */ return false; |