From 052cc695423560ca70ef296930019774bf6b659b Mon Sep 17 00:00:00 2001 From: Ashutosh Bapat Date: Mon, 4 Sep 2023 14:56:21 +0530 Subject: [PATCH 3/4] Save commuted RestrictInfo for later use A commuted RestrictInfo may be produced as many times as the number of indexes it is used for. It's the same RestrictInfo always. Save some CPU and memory by saving the result in the original RestrictInfo. Ashutosh Bapat --- src/backend/optimizer/util/appendinfo.c | 6 ++++++ src/backend/optimizer/util/restrictinfo.c | 22 +++++++++++++++++++++- src/include/nodes/pathnodes.h | 9 +++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/backend/optimizer/util/appendinfo.c b/src/backend/optimizer/util/appendinfo.c index 4008e52de2..53e1233dce 100644 --- a/src/backend/optimizer/util/appendinfo.c +++ b/src/backend/optimizer/util/appendinfo.c @@ -492,6 +492,12 @@ adjust_appendrel_attrs_mutator(Node *node, newinfo->left_mcvfreq = -1; newinfo->right_mcvfreq = -1; + /* + * Wipe out commuted parent RestrictInfo. The caller will compute + * commuted clause if required. + */ + newinfo->comm_rinfo = NULL; + return (Node *) newinfo; } diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index d6d26a2b51..9d67c623d0 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->comm_rinfo = NULL; + restrictinfo->is_commuted = false; return restrictinfo; } @@ -354,14 +356,27 @@ make_sub_restrictinfos(PlannerInfo *root, * be hazardous if the source is subject to change. Also notice that we * assume without checking that the commutator op is a member of the same * btree and hash opclasses as the original op. + * + * If a commuted RestrictInfo is already available it is returned. */ RestrictInfo * commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op) { RestrictInfo *result; OpExpr *newclause; - OpExpr *clause = castNode(OpExpr, rinfo->clause); + OpExpr *clause; + + if (rinfo->comm_rinfo) + { + result = rinfo->comm_rinfo; + newclause = castNode(OpExpr, result->clause); + Assert(list_length(newclause->args) == 2); + Assert(newclause->opno == comm_op); + return result; + } + + clause = castNode(OpExpr, rinfo->clause); Assert(list_length(clause->args) == 2); /* flat-copy all the fields of clause ... */ @@ -403,6 +418,11 @@ commute_restrictinfo(RestrictInfo *rinfo, Oid comm_op) result->right_mcvfreq = rinfo->left_mcvfreq; result->left_hasheqoperator = InvalidOid; result->right_hasheqoperator = InvalidOid; + result->is_commuted = !rinfo->is_commuted; + result->comm_rinfo = rinfo; + + /* Save the commuted RestrictInfo for later use. */ + rinfo->comm_rinfo = result; return result; } diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index 5702fbba60..c575fd11ec 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -2517,6 +2517,13 @@ typedef struct LimitPath * * parent_ec, left_ec, right_ec are not printed, lest it lead to infinite * recursion in plan tree dump. + * + * A RestrictInfo may get commuted as many times as the number of indexes it is + * used for. The commuted clause is cached in the original RestrictInfo as + * comm_rinfo and vice versa. Both the RestrictInfos are commuted versions of + * each other. is_commuted flag is false for the first one to appear and is + * true in the other. The order doesn't matter. The flag just differentiate + * between the commuted version. */ typedef struct RestrictInfo @@ -2668,6 +2675,8 @@ 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); + struct RestrictInfo *comm_rinfo pg_node_attr(equal_ignore); + bool is_commuted pg_node_attr(equal_ignore); } RestrictInfo; /* -- 2.25.1