aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/plan/planner.c
diff options
context:
space:
mode:
authorDavid Rowley <drowley@postgresql.org>2023-07-03 12:49:43 +1200
committerDavid Rowley <drowley@postgresql.org>2023-07-03 12:49:43 +1200
commitc65102006b686ea26194fb539d7a416a089300e0 (patch)
tree494a8ac701ea4ac6b158136140fd15e254deadc7 /src/backend/optimizer/plan/planner.c
parent4637a6ac0b40fef701ab850de1be547b927c3013 (diff)
downloadpostgresql-c65102006b686ea26194fb539d7a416a089300e0.tar.gz
postgresql-c65102006b686ea26194fb539d7a416a089300e0.zip
Remove redundant PARTITION BY columns from WindowClauses
Here we adjust the query planner to have it remove items from a window clause's PARTITION BY clause in cases where the pathkey for a column in the PARTITION BY clause is redundant. Doing this allows the optimization added in 9d9c02ccd to stop window aggregation early rather than going into "pass-through" mode to find tuples belonging to the next partition. Also, when we manage to remove all PARTITION BY columns, we now no longer needlessly check that the current tuple belongs to the same partition as the last tuple in nodeWindowAgg.c. If the pathkey was redundant then all tuples must contain the same value for the given redundant column, so there's no point in checking that during execution. Author: David Rowley Reviewed-by: Richard Guo Discussion: https://postgr.es/m/CAApHDvo2ji+hdxrxfXtRtsfSVw3to2o1nCO20qimw0dUGK8hcQ@mail.gmail.com
Diffstat (limited to 'src/backend/optimizer/plan/planner.c')
-rw-r--r--src/backend/optimizer/plan/planner.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 1e4dd27dbaf..eaee9eda771 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -5999,6 +5999,9 @@ make_window_input_target(PlannerInfo *root,
* Create a pathkeys list describing the required input ordering
* for the given WindowClause.
*
+ * Modifies wc's partitionClause to remove any clauses which are deemed
+ * redundant by the pathkey logic.
+ *
* The required ordering is first the PARTITION keys, then the ORDER keys.
* In the future we might try to implement windowing using hashing, in which
* case the ordering could be relaxed, but for now we always sort.
@@ -6007,8 +6010,7 @@ static List *
make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
List *tlist)
{
- List *window_pathkeys;
- List *window_sortclauses;
+ List *window_pathkeys = NIL;
/* Throw error if can't sort */
if (!grouping_is_sortable(wc->partitionClause))
@@ -6022,12 +6024,45 @@ make_pathkeys_for_window(PlannerInfo *root, WindowClause *wc,
errmsg("could not implement window ORDER BY"),
errdetail("Window ordering columns must be of sortable datatypes.")));
- /* Okay, make the combined pathkeys */
- window_sortclauses = list_concat_copy(wc->partitionClause, wc->orderClause);
- window_pathkeys = make_pathkeys_for_sortclauses(root,
- window_sortclauses,
- tlist);
- list_free(window_sortclauses);
+ /*
+ * First fetch the pathkeys for the PARTITION BY clause. We can safely
+ * remove any clauses from the wc->partitionClause for redundant pathkeys.
+ */
+ if (wc->partitionClause != NIL)
+ {
+ bool sortable;
+
+ window_pathkeys = make_pathkeys_for_sortclauses_extended(root,
+ &wc->partitionClause,
+ tlist,
+ true,
+ &sortable);
+
+ Assert(sortable);
+ }
+
+ /*
+ * In principle, we could also consider removing redundant ORDER BY items
+ * too as doing so does not alter the result of peer row checks done by
+ * the executor. However, we must *not* remove the ordering column for
+ * RANGE OFFSET cases, as the executor needs that for in_range tests even
+ * if it's known to be equal to some partitioning column.
+ */
+ if (wc->orderClause != NIL)
+ {
+ List *orderby_pathkeys;
+
+ orderby_pathkeys = make_pathkeys_for_sortclauses(root,
+ wc->orderClause,
+ tlist);
+
+ /* Okay, make the combined pathkeys */
+ if (window_pathkeys != NIL)
+ window_pathkeys = append_pathkeys(window_pathkeys, orderby_pathkeys);
+ else
+ window_pathkeys = orderby_pathkeys;
+ }
+
return window_pathkeys;
}