From 914032be56e6d6601e9638770a5bb926edb240e2 Mon Sep 17 00:00:00 2001 From: Lyu Pan Date: Fri, 16 Sep 2022 21:40:59 +0000 Subject: [PATCH 6/7] Integrate EXPLAIN command with semijoin filter. When explaining Merge Join node, if semijoin filter is used in the Merge Join node, related metadata will be displyed, including filter clause, estimated filtering rate and actual filtering rate if EXPLAIN ANALYZE is used. For example: Merge Join (...) Merge Cond: (...) SemiJoin Filter Created Based on: (...) SemiJoin Estimated Filtering Rate: XXX SemiJoin Actual Filtering Rate: XXX --- src/backend/commands/explain.c | 40 +++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index f86983c6601..438792e31ab 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -153,7 +153,8 @@ static void ExplainIndentText(ExplainState *es); static void ExplainJSONLineEnding(ExplainState *es); static void ExplainYAMLLineStarting(ExplainState *es); static void escape_yaml(StringInfo buf, const char *str); - +static void show_semijoin_metadata(List *equijoins, PlanState *planstate, + List *ancestors, ExplainState *es); /* @@ -1981,6 +1982,11 @@ ExplainNode(PlanState *planstate, List *ancestors, "Merge Cond", planstate, ancestors, es); show_upper_qual(((MergeJoin *) plan)->join.joinqual, "Join Filter", planstate, ancestors, es); + if (((MergeJoinState *) planstate)->sjf) + { + show_semijoin_metadata(((MergeJoin *) plan)->mergeclauses, + planstate, ancestors, es); + } if (((MergeJoin *) plan)->join.joinqual) show_instrumentation_count("Rows Removed by Join Filter", 1, planstate, es); @@ -5041,3 +5047,35 @@ escape_yaml(StringInfo buf, const char *str) { escape_json(buf, str); } + +static void +show_semijoin_metadata(List *equijoins, PlanState *planstate, + List *ancestors, ExplainState *es) +{ + char createStr[256]; + int clause_ordinal; + Node *best_equijoin_clause; + MergeJoin *mj = ((MergeJoin *) planstate->plan); + + Assert(planstate); + Assert(nodeTag(planstate) == T_MergeJoinState); + Assert(planstate->plan); + Assert(nodeTag(planstate->plan) == T_MergeJoin); + + snprintf(createStr, sizeof(createStr), "%s", + "SemiJoin Filter Created Based on"); + clause_ordinal = mj->bestExpr; + best_equijoin_clause = + (Node *) list_nth_node(OpExpr, equijoins, clause_ordinal); + show_expression(best_equijoin_clause, createStr, planstate, ancestors, + true, es); + ExplainPropertyFloat("SemiJoin Estimated Filtering Rate", NULL, + mj->filteringRate, 4, es); + if (es->analyze) + { + SemiJoinFilter *sjf = ((MergeJoinState *) planstate)->sjf; + + ExplainPropertyFloat("SemiJoin Actual Filtering Rate", NULL, + ((double) sjf->elementsFiltered) / sjf->elementsChecked, 4, es); + } +} -- 2.37.3