v2-0002-Teach-group_keys_reorder_by_pathkeys-about-redund.patch
application/octet-stream
Filename: v2-0002-Teach-group_keys_reorder_by_pathkeys-about-redund.patch
Type: application/octet-stream
Part: 2
Message:
Re: POC: GROUP BY optimization
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v2-0002
Subject: Teach group_keys_reorder_by_pathkeys() about redundant SortGroupClause's
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/pathkeys.c | 55 | 14 |
From b5ea90e50faf8a7a8fc2329a35da5f66fbe3d35b Mon Sep 17 00:00:00 2001
From: Alexander Korotkov <akorotkov@postgresql.org>
Date: Tue, 21 May 2024 03:13:11 +0300
Subject: [PATCH v2 2/4] Teach group_keys_reorder_by_pathkeys() about redundant
SortGroupClause's
We don't have strict guarantees that there shouldn't be redundant
SortGroupClause's. Although there is no confirmed way to generate
duplicate SortGroupClause's, this commit teaches
group_keys_reorder_by_pathkeys() to pull all the SortGroupClause matching to
pathkey at once.
This commit also introduces checking invariants of generated orderings
in get_useful_group_keys_orderings for assert-enabled builds.
Discussion: https://postgr.es/m/a663f0f6-cbf6-49aa-af2e-234dc6768a07%40postgrespro.ru
Author: Andrei Lepikhov
---
src/backend/optimizer/path/pathkeys.c | 69 +++++++++++++++++++++------
1 file changed, 55 insertions(+), 14 deletions(-)
diff --git a/src/backend/optimizer/path/pathkeys.c b/src/backend/optimizer/path/pathkeys.c
index 7858a56fae0..e8ff2297697 100644
--- a/src/backend/optimizer/path/pathkeys.c
+++ b/src/backend/optimizer/path/pathkeys.c
@@ -401,7 +401,7 @@ group_keys_reorder_by_pathkeys(List *pathkeys, List **group_pathkeys,
foreach(lc, pathkeys)
{
PathKey *pathkey = (PathKey *) lfirst(lc);
- SortGroupClause *sgc;
+ bool found = false;
/*
* Pathkeys are built in a way that allows simply comparing pointers.
@@ -416,28 +416,40 @@ group_keys_reorder_by_pathkeys(List *pathkeys, List **group_pathkeys,
/*
* Since 1349d27 pathkey coming from underlying node can be in the
* root->group_pathkeys but not in the processed_groupClause. So, we
- * should be careful here.
+ * should be careful here. Also, there could be redundant
+ * SortGroupClause's. So, we need to pull of all the matching
+ * SortGroupClause's, but ensure there is at least one.
*/
- sgc = get_sortgroupref_clause_noerr(pathkey->pk_eclass->ec_sortref,
- *group_clauses);
- if (!sgc)
- /* The grouping clause does not cover this pathkey */
- break;
+ foreach_ptr(SortGroupClause, sgc, *group_clauses)
+ {
+ if (sgc->tleSortGroupRef == pathkey->pk_eclass->ec_sortref)
+ {
+ /*
+ * Sort group clause should have an ordering operator as long
+ * as there is an associated pathkey.
+ */
+ Assert(OidIsValid(sgc->sortop));
- /*
- * Sort group clause should have an ordering operator as long as there
- * is an associated pathkey.
- */
- Assert(OidIsValid(sgc->sortop));
+ new_group_clauses = lappend(new_group_clauses, sgc);
+ found = true;
+ }
+ }
+
+ /* Check if the grouping clause does not cover this pathkey */
+ if (!found)
+ break;
new_group_pathkeys = lappend(new_group_pathkeys, pathkey);
- new_group_clauses = lappend(new_group_clauses, sgc);
+
}
/* remember the number of pathkeys with a matching GROUP BY key */
n = list_length(new_group_pathkeys);
- /* append the remaining group pathkeys (will be treated as not sorted) */
+ /*
+ * Append the remaining group pathkeys (will be treated as not sorted) and
+ * grouping clauses.
+ */
*group_pathkeys = list_concat_unique_ptr(new_group_pathkeys,
*group_pathkeys);
*group_clauses = list_concat_unique_ptr(new_group_clauses,
@@ -561,6 +573,35 @@ get_useful_group_keys_orderings(PlannerInfo *root, Path *path)
}
}
+#ifdef USE_ASSERT_CHECKING
+ {
+ PathKeyInfo *pinfo = linitial_node(PathKeyInfo, infos);
+ ListCell *lc;
+
+ /* Test consistency of info structures */
+ for_each_from(lc, infos, 1)
+ {
+ ListCell *lc1,
+ *lc2;
+
+ info = lfirst_node(PathKeyInfo, lc);
+
+ Assert(list_length(info->clauses) == list_length(pinfo->clauses));
+ Assert(list_length(info->pathkeys) == list_length(pinfo->pathkeys));
+ Assert(list_difference(info->clauses, pinfo->clauses) == NIL);
+ Assert(list_difference_ptr(info->pathkeys, pinfo->pathkeys) == NIL);
+
+ forboth(lc1, info->clauses, lc2, info->pathkeys)
+ {
+ SortGroupClause *sgc = lfirst_node(SortGroupClause, lc1);
+ PathKey *pk = lfirst_node(PathKey, lc2);
+
+ if (pk->pk_eclass->ec_sortref != sgc->tleSortGroupRef)
+ elog(ERROR, "Order of group-by clauses doesn't correspond incoming sort order");
+ }
+ }
+ }
+#endif
return infos;
}
--
2.39.3 (Apple Git-145)