From 99f06a021fc4330ba1fcbf61f4c0e085b96df500 Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Thu, 22 Jun 2023 14:27:14 +0530 Subject: [PATCH 2/7] Avoid translating RestrictInfo repeatedly RestrictInfo to be applied to the child rels (including the child join rels) are obtained by translating RestrictInfo applicable to the parent rel. Since these translations are not tracked, the same RestrictInfo may get translated multiple times for the same parent and child pair. When using partitionwise join this can happen as many times as the number of possible join orders between the partitioned tables. Every translated RestrictInfo is stored in the top parent's RestrictInfo in a list. Every translated RestrictInfo contains a pointer to the top parent's RestrictInfo to track multilevel translations. RestrictInfo::required_relids is used as a key to search a given translation. adjust_appendrel_attrs_mutator() first looks up an existing translations when translating a RestrictInfo and creates a new one only when one doesn't exist. Ashutosh Bapat --- src/backend/optimizer/util/appendinfo.c | 47 ++++++++++++++++++++++- src/backend/optimizer/util/restrictinfo.c | 2 + src/include/nodes/pathnodes.h | 7 ++++ 3 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c index f456b3b0a4..70a5ff2750 100644 --- a/src/backend/optimizer/util/appendinfo.c +++ b/src/backend/optimizer/util/appendinfo.c @@ -217,6 +217,7 @@ adjust_appendrel_attrs_mutator(Node *node, { AppendRelInfo **appinfos = context->appinfos; int nappinfos = context->nappinfos; + PlannerInfo *root = context->root; int cnt; if (node == NULL) @@ -445,7 +446,46 @@ adjust_appendrel_attrs_mutator(Node *node, if (IsA(node, RestrictInfo)) { RestrictInfo *oldinfo = (RestrictInfo *) node; - RestrictInfo *newinfo = makeNode(RestrictInfo); + Relids child_required_relids = adjust_child_relids(oldinfo->required_relids, + nappinfos, appinfos); + RestrictInfo *parent_rinfo; + ListCell *lc; + RestrictInfo *newinfo; + MemoryContext old_context; + + /* + * If the adjusted RestrictInfo already exists, use it otherwise create + * a new one. This avoids translating the same RestrictInfo again and + * again wasting memory especially in partitionwise joins. + */ + + if (bms_equal(child_required_relids, oldinfo->required_relids)) + { + /* If the clause does not need any translation. */ + bms_free(child_required_relids); + return (Node *) oldinfo; + } + + /* + * Check if we already have the RestrictInfo for the given child in the + * topmost parent's RestrictInfo. + */ + parent_rinfo = oldinfo->parent_rinfo ? oldinfo->parent_rinfo : oldinfo; + foreach (lc, parent_rinfo->child_rinfos) + { + newinfo = lfirst(lc); + + if (bms_equal(newinfo->required_relids, child_required_relids)) + { + bms_free(child_required_relids); + return (Node *) newinfo; + } + } + bms_free(child_required_relids); + + /* Translate in a long lasting memory context. */ + old_context = MemoryContextSwitchTo(root->planner_cxt); + newinfo = makeNode(RestrictInfo); /* Copy all flat-copiable fields, notably including rinfo_serial */ memcpy(newinfo, oldinfo, sizeof(RestrictInfo)); @@ -491,6 +531,11 @@ adjust_appendrel_attrs_mutator(Node *node, newinfo->right_bucketsize = -1; newinfo->left_mcvfreq = -1; newinfo->right_mcvfreq = -1; + newinfo->parent_rinfo = parent_rinfo; + parent_rinfo->child_rinfos = lappend(parent_rinfo->child_rinfos, + newinfo); + + MemoryContextSwitchTo(old_context); return (Node *) newinfo; } diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index d6d26a2b51..7a97ab7407 100644 --- a/src/backend/optimizer/util/restrictinfo.c +++ b/src/backend/optimizer/util/restrictinfo.c @@ -246,6 +246,8 @@ make_restrictinfo_internal(PlannerInfo *root, restrictinfo->left_hasheqoperator = InvalidOid; restrictinfo->right_hasheqoperator = InvalidOid; + restrictinfo->child_rinfos = NIL; + restrictinfo->parent_rinfo = NULL; return restrictinfo; } diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index c17b53f7ad..a064629626 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -2655,6 +2655,13 @@ typedef struct RestrictInfo /* hash equality operators used for memoize nodes, else InvalidOid */ Oid left_hasheqoperator pg_node_attr(equal_ignore); Oid right_hasheqoperator pg_node_attr(equal_ignore); + + /* Only one of these two can be set. */ + List *child_rinfos pg_node_attr(equal_ignore, copy_as(NIL)); /* RestrictInfos derived for children. */ + struct RestrictInfo *parent_rinfo pg_node_attr(equal_ignore, copy_as(NULL)); /* Parent restrictinfo this + * RestrictInf is derived from. + */ + } RestrictInfo; /* -- 2.25.1