diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-11-06 22:31:24 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-11-06 22:31:24 +0000 |
commit | 2103b7baa26fe25cc2b5bee802028caeabb28113 (patch) | |
tree | f7516bbb3b18fca352fd638d567b2b0bf3a5a0bd /src/backend/optimizer | |
parent | fc9814d17e7701bac198c99f8ab9f67c8468797f (diff) | |
download | postgresql-2103b7baa26fe25cc2b5bee802028caeabb28113.tar.gz postgresql-2103b7baa26fe25cc2b5bee802028caeabb28113.zip |
Phase 2 of hashed-aggregation project. nodeAgg.c now knows how to do
hashed aggregation, but there's not yet planner support for it.
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r-- | src/backend/optimizer/plan/createplan.c | 3 | ||||
-rw-r--r-- | src/backend/optimizer/plan/planner.c | 63 | ||||
-rw-r--r-- | src/backend/optimizer/util/clauses.c | 29 |
3 files changed, 80 insertions, 15 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 5a2acbd2763..cba1b2027d3 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.120 2002/11/06 00:00:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/createplan.c,v 1.121 2002/11/06 22:31:24 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1675,6 +1675,7 @@ make_agg(List *tlist, List *qual, AggStrategy aggstrategy, plan->plan_rows *= 0.1; if (plan->plan_rows < 1) plan->plan_rows = 1; + node->numGroups = (long) plan->plan_rows; } plan->state = (EState *) NULL; diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index cc8e7a698d5..7e722d6a099 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.126 2002/11/06 00:00:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/planner.c,v 1.127 2002/11/06 22:31:24 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -931,6 +931,7 @@ grouping_planner(Query *parse, double tuple_fraction) AttrNumber *groupColIdx = NULL; Path *cheapest_path; Path *sorted_path; + bool use_hashed_grouping = false; /* Preprocess targetlist in case we are inside an INSERT/UPDATE. */ tlist = preprocess_targetlist(tlist, @@ -1210,6 +1211,29 @@ grouping_planner(Query *parse, double tuple_fraction) sort_pathkeys = canonicalize_pathkeys(parse, sort_pathkeys); /* + * Consider whether we might want to use hashed grouping. + */ + if (parse->groupClause) + { + /* + * Executor doesn't support hashed aggregation with DISTINCT + * aggregates. (Doing so would imply storing *all* the input + * values in the hash table, which seems like a certain loser.) + */ + if (parse->hasAggs && + (contain_distinct_agg_clause((Node *) tlist) || + contain_distinct_agg_clause(parse->havingQual))) + use_hashed_grouping = false; + else + { +#if 0 /* much more to do here */ + /* TEMPORARY HOTWIRE FOR TESTING */ + use_hashed_grouping = true; +#endif + } + } + + /* * Select the best path and create a plan to execute it. * * If no special sort order is wanted, or if the cheapest path is @@ -1279,22 +1303,30 @@ grouping_planner(Query *parse, double tuple_fraction) } /* - * If any aggregate is present, insert the Agg node, plus an explicit - * sort if necessary. + * Insert AGG or GROUP node if needed, plus an explicit sort step + * if necessary. * * HAVING clause, if any, becomes qual of the Agg node */ - if (parse->hasAggs) + if (use_hashed_grouping) { + /* Hashed aggregate plan --- no sort needed */ + result_plan = (Plan *) make_agg(tlist, + (List *) parse->havingQual, + AGG_HASHED, + length(parse->groupClause), + groupColIdx, + result_plan); + /* Hashed aggregation produces randomly-ordered results */ + current_pathkeys = NIL; + } + else if (parse->hasAggs) + { + /* Plain aggregate plan --- sort if needed */ AggStrategy aggstrategy; if (parse->groupClause) { - aggstrategy = AGG_SORTED; - /* - * Add an explicit sort if we couldn't make the path come out - * the way the AGG node needs it. - */ if (!pathkeys_contained_in(group_pathkeys, current_pathkeys)) { result_plan = make_groupsortplan(parse, @@ -1303,9 +1335,18 @@ grouping_planner(Query *parse, double tuple_fraction) result_plan); current_pathkeys = group_pathkeys; } + aggstrategy = AGG_SORTED; + /* + * The AGG node will not change the sort ordering of its + * groups, so current_pathkeys describes the result too. + */ } else + { aggstrategy = AGG_PLAIN; + /* Result will be only one row anyway; no sort order */ + current_pathkeys = NIL; + } result_plan = (Plan *) make_agg(tlist, (List *) parse->havingQual, @@ -1313,10 +1354,6 @@ grouping_planner(Query *parse, double tuple_fraction) length(parse->groupClause), groupColIdx, result_plan); - /* - * Note: plain or grouped Agg does not affect any existing - * sort order of the tuples - */ } else { diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c index ee037974769..f55c988bfc5 100644 --- a/src/backend/optimizer/util/clauses.c +++ b/src/backend/optimizer/util/clauses.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.109 2002/09/11 14:48:54 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/clauses.c,v 1.110 2002/11/06 22:31:24 tgl Exp $ * * HISTORY * AUTHOR DATE MAJOR EVENT @@ -46,6 +46,7 @@ typedef struct } check_subplans_for_ungrouped_vars_context; static bool contain_agg_clause_walker(Node *node, void *context); +static bool contain_distinct_agg_clause_walker(Node *node, void *context); static bool pull_agg_clause_walker(Node *node, List **listptr); static bool expression_returns_set_walker(Node *node, void *context); static bool contain_subplans_walker(Node *node, void *context); @@ -411,6 +412,32 @@ contain_agg_clause_walker(Node *node, void *context) } /* + * contain_distinct_agg_clause + * Recursively search for DISTINCT Aggref nodes within a clause. + * + * Returns true if any DISTINCT aggregate found. + */ +bool +contain_distinct_agg_clause(Node *clause) +{ + return contain_distinct_agg_clause_walker(clause, NULL); +} + +static bool +contain_distinct_agg_clause_walker(Node *node, void *context) +{ + if (node == NULL) + return false; + if (IsA(node, Aggref)) + { + if (((Aggref *) node)->aggdistinct) + return true; /* abort the tree traversal and return + * true */ + } + return expression_tree_walker(node, contain_distinct_agg_clause_walker, context); +} + +/* * pull_agg_clause * Recursively pulls all Aggref nodes from an expression tree. * |