diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c index 000d757bdd..781916f219 100644 --- a/src/backend/optimizer/plan/planner.c +++ b/src/backend/optimizer/plan/planner.c @@ -4423,6 +4423,7 @@ create_one_window_path(PlannerInfo *root, PathTarget *window_target; ListCell *l; List *topqual = NIL; + bool has_runcondition = false; /* * Since each window clause could require a different sort order, we stack @@ -4457,6 +4458,42 @@ create_one_window_path(PlannerInfo *root, path->pathkeys, &presorted_keys); + has_runcondition |= (wc->runCondition != NIL); + + /* + * If not sorted already and the query has an ORDER BY clause, then we + * try to push the entire ORDER BY below the final WindowAgg. We + * don't do this when the query has a DISTINCT clause as the planner + * might opt to do a Hash Aggregate and spoil our efforts here. We + * also can't do this when the ORDER BY contains any WindowFuncs as we + * obviously can't sort something that's yet to be evaluated. We also + * don't bother with this when there is a WindowClauses with a + * runCondition as those can reduce the number of rows to sort in the + * ORDER BY and we don't want add complexity to the WindowAgg sort if + * the final ORDER BY sort is going to have far fewer rows to sort. + * For the same reason, don't bother if the query has a LIMIT clause. + */ + if (!is_sorted && lnext(activeWindows, l) == NULL && + root->parse->distinctClause == NIL && + root->parse->sortClause != NIL && + !has_runcondition && root->parse->limitCount == NULL && + !contain_window_function((Node *) get_sortgrouplist_exprs(root->parse->sortClause, + root->processed_tlist))) + { + List *orderby_pathkeys; + + orderby_pathkeys = make_pathkeys_for_sortclauses(root, + root->parse->sortClause, + root->processed_tlist); + + if (pathkeys_contained_in(window_pathkeys, orderby_pathkeys)) + window_pathkeys = orderby_pathkeys; + + is_sorted = pathkeys_count_contained_in(window_pathkeys, + path->pathkeys, + &presorted_keys); + } + /* Sort if necessary */ if (!is_sorted) {