diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 54 |
1 files changed, 33 insertions, 21 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index a66317367c3..ddf1109de76 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -114,6 +114,7 @@ static Size estimate_hashagg_tablesize(Path *path, static RelOptInfo *create_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, + const AggClauseCosts *agg_costs, List *rollup_lists, List *rollup_groupclauses); static RelOptInfo *create_window_paths(PlannerInfo *root, @@ -1499,6 +1500,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, PathTarget *grouping_target; PathTarget *scanjoin_target; bool have_grouping; + AggClauseCosts agg_costs; WindowFuncLists *wflists = NULL; List *activeWindows = NIL; List *rollup_lists = NIL; @@ -1624,6 +1626,28 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, root->processed_tlist = tlist; /* + * 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. + */ + MemSet(&agg_costs, 0, sizeof(AggClauseCosts)); + if (parse->hasAggs) + { + get_agg_clause_costs(root, (Node *) tlist, AGGSPLIT_SIMPLE, + &agg_costs); + get_agg_clause_costs(root, parse->havingQual, AGGSPLIT_SIMPLE, + &agg_costs); + } + + /* * Locate any window functions in the tlist. (We don't need to look * anywhere else, since expressions used in ORDER BY will be in there * too.) Note that they could all have been eliminated by constant @@ -1822,6 +1846,7 @@ grouping_planner(PlannerInfo *root, bool inheritance_update, current_rel = create_grouping_paths(root, current_rel, grouping_target, + &agg_costs, rollup_lists, rollup_groupclauses); } @@ -3244,6 +3269,7 @@ estimate_hashagg_tablesize(Path *path, const AggClauseCosts *agg_costs, * * 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) * rollup_lists: list of grouping sets, or NIL if not doing grouping sets * rollup_groupclauses: list of grouping clauses for grouping sets, * or NIL if not doing grouping sets @@ -3260,6 +3286,7 @@ static RelOptInfo * create_grouping_paths(PlannerInfo *root, RelOptInfo *input_rel, PathTarget *target, + const AggClauseCosts *agg_costs, List *rollup_lists, List *rollup_groupclauses) { @@ -3267,7 +3294,6 @@ create_grouping_paths(PlannerInfo *root, Path *cheapest_path = input_rel->cheapest_total_path; RelOptInfo *grouped_rel; PathTarget *partial_grouping_target = NULL; - AggClauseCosts agg_costs; AggClauseCosts agg_partial_costs; /* parallel only */ AggClauseCosts agg_final_costs; /* parallel only */ Size hashaggtablesize; @@ -3365,20 +3391,6 @@ create_grouping_paths(PlannerInfo *root, } /* - * Collect statistics about aggregates for estimating costs. Note: we do - * not detect duplicate aggregates here; a somewhat-overestimated cost is - * okay for our purposes. - */ - MemSet(&agg_costs, 0, sizeof(AggClauseCosts)); - if (parse->hasAggs) - { - get_agg_clause_costs(root, (Node *) target->exprs, AGGSPLIT_SIMPLE, - &agg_costs); - get_agg_clause_costs(root, parse->havingQual, AGGSPLIT_SIMPLE, - &agg_costs); - } - - /* * Estimate number of groups. */ dNumGroups = get_number_of_groups(root, @@ -3414,7 +3426,7 @@ create_grouping_paths(PlannerInfo *root, */ can_hash = (parse->groupClause != NIL && parse->groupingSets == NIL && - agg_costs.numOrderedAggs == 0 && + agg_costs->numOrderedAggs == 0 && grouping_is_hashable(parse->groupClause)); /* @@ -3446,7 +3458,7 @@ create_grouping_paths(PlannerInfo *root, /* We don't know how to do grouping sets in parallel. */ try_parallel_aggregation = false; } - else if (agg_costs.hasNonPartial || agg_costs.hasNonSerial) + else if (agg_costs->hasNonPartial || agg_costs->hasNonSerial) { /* Insufficient support for partial mode. */ try_parallel_aggregation = false; @@ -3627,7 +3639,7 @@ create_grouping_paths(PlannerInfo *root, (List *) parse->havingQual, rollup_lists, rollup_groupclauses, - &agg_costs, + agg_costs, dNumGroups)); } else if (parse->hasAggs) @@ -3645,7 +3657,7 @@ create_grouping_paths(PlannerInfo *root, AGGSPLIT_SIMPLE, parse->groupClause, (List *) parse->havingQual, - &agg_costs, + agg_costs, dNumGroups)); } else if (parse->groupClause) @@ -3727,7 +3739,7 @@ create_grouping_paths(PlannerInfo *root, if (can_hash) { hashaggtablesize = estimate_hashagg_tablesize(cheapest_path, - &agg_costs, + agg_costs, dNumGroups); /* @@ -3751,7 +3763,7 @@ create_grouping_paths(PlannerInfo *root, AGGSPLIT_SIMPLE, parse->groupClause, (List *) parse->havingQual, - &agg_costs, + agg_costs, dNumGroups)); } |