window_prefix_sort.patch
application/octet-stream
Filename: window_prefix_sort.patch
Type: application/octet-stream
Part: 0
Patch
Format: format-patch
Subject: Order windows on partition/ordering prefix to reuse Sort nodes
| File | + | − |
|---|---|---|
| src/backend/optimizer/plan/planner.c | 47 | 34 |
From eba463f191d59485225f38b56d0597d750417957 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Wed, 30 May 2018 10:16:23 -0400
Subject: [PATCH] Order windows on partition/ordering prefix to reuse Sort
nodes
By ordering the Windows on partitioning/ordering prefix, the result
from Sort nodes can be reused by multiple WindowAgg nodes and thus
we can avoid Sort nodes.
---
src/backend/optimizer/plan/planner.c | 81 +++++++++++++++++++++---------------
1 file changed, 47 insertions(+), 34 deletions(-)
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 67a2c7a581..4431d0c2a9 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -237,6 +237,8 @@ static void create_partitionwise_grouping_paths(PlannerInfo *root,
static bool group_by_has_partkey(RelOptInfo *input_rel,
List *targetList,
List *groupClause);
+static int common_prefix_cmp(const void *a, const void *b);
+
/*****************************************************************************
@@ -5251,7 +5253,6 @@ postprocess_setop_tlist(List *new_tlist, List *orig_tlist)
static List *
select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
{
- List *result;
List *actives;
ListCell *lc;
@@ -5273,43 +5274,55 @@ select_active_windows(PlannerInfo *root, WindowFuncLists *wflists)
* says that only one sort is to be used for such windows, even if they
* are otherwise distinct (eg, different names or framing clauses).
*
- * There is room to be much smarter here, for example detecting whether
- * one window's sort keys are a prefix of another's (so that sorting for
- * the latter would do for the former), or putting windows first that
- * match a sort order available for the underlying query. For the moment
- * we are content with meeting the spec.
- */
- result = NIL;
- while (actives != NIL)
- {
- WindowClause *wc = linitial_node(WindowClause, actives);
- ListCell *prev;
- ListCell *next;
-
- /* Move wc from actives to result */
- actives = list_delete_first(actives);
- result = lappend(result, wc);
+ * Also sort windows by partitioning/ordering prefixes where the sorting
+ * required for a window will cover the sorting required for another
+ * window, thus reducing the number of Sort nodes.
+ */
+ if (list_length(actives) > 1)
+ actives = list_qsort(actives, common_prefix_cmp);
- /* Now move any matching windows from actives to result */
- prev = NULL;
- for (lc = list_head(actives); lc; lc = next)
- {
- WindowClause *wc2 = lfirst_node(WindowClause, lc);
+ return actives;
+}
- next = lnext(lc);
- /* framing options are NOT to be compared here! */
- if (equal(wc->partitionClause, wc2->partitionClause) &&
- equal(wc->orderClause, wc2->orderClause))
- {
- actives = list_delete_cell(actives, lc, prev);
- result = lappend(result, wc2);
- }
- else
- prev = lc;
- }
+static int
+common_prefix_cmp(const void *a, const void *b)
+{
+ WindowClause *wca = (WindowClause *) lfirst(*(ListCell **) a);
+ WindowClause *wcb = (WindowClause *) lfirst(*(ListCell **) b);
+ List *aa = NIL;
+ List *bb = NIL;
+ ListCell *item_a;
+ ListCell *item_b;
+ int lla;
+ int llb;
+
+ aa = list_concat_unique(list_copy(wca->partitionClause), wca->orderClause);
+ bb = list_concat_unique(list_copy(wcb->partitionClause), wcb->orderClause);
+
+ forboth(item_a, aa, item_b, bb)
+ {
+ SortGroupClause *sca = lfirst(item_a);
+ SortGroupClause *scb = lfirst(item_b);
+
+ if (sca->tleSortGroupRef < scb->tleSortGroupRef)
+ return -1;
+ else if (sca->tleSortGroupRef > scb->tleSortGroupRef)
+ return 1;
+ else if (sca->sortop < scb->sortop)
+ return -1;
+ else if (sca->sortop > scb->sortop)
+ return 1;
}
- return result;
+ lla = list_length(aa);
+ llb = list_length(bb);
+
+ if (lla < llb)
+ return -1;
+ else if (lla > llb)
+ return 1;
+
+ return 0;
}
/*
--
2.14.1.145.gb3622a4ee