v3-0002-add-a-GUC-goo_greedy_strategy-to-choose-different.patch
application/octet-stream
Filename: v3-0002-add-a-GUC-goo_greedy_strategy-to-choose-different.patch
Type: application/octet-stream
Part: 2
From 5777b1bd17e06fdbc5e8cf55bee6ae38ad623d76 Mon Sep 17 00:00:00 2001
From: Chengpeng Yan <chengpeng_yan@outlook.com>
Date: Tue, 16 Dec 2025 20:15:44 +0800
Subject: [PATCH v3 2/2] add a GUC goo_greedy_strategy to choose different GOO
greedy strategic to test
Signed-off-by: Chengpeng Yan <chengpeng_yan@outlook.com>
---
src/backend/optimizer/path/goo.c | 36 ++++++++++++++++++++++-
src/backend/utils/misc/guc_parameters.dat | 10 +++++++
src/backend/utils/misc/guc_tables.c | 8 +++++
src/include/optimizer/paths.h | 8 +++++
4 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/src/backend/optimizer/path/goo.c b/src/backend/optimizer/path/goo.c
index 247dbb5f921..64ea7667315 100644
--- a/src/backend/optimizer/path/goo.c
+++ b/src/backend/optimizer/path/goo.c
@@ -55,6 +55,7 @@
* Configuration defaults. These are exposed as GUCs in guc_tables.c.
*/
bool enable_goo_join_search = false;
+int goo_greedy_strategy = GOO_GREEDY_STRATEGY_COST;
/*
* Working state for a single GOO search invocation.
@@ -94,6 +95,9 @@ typedef struct GooCandidate
{
RelOptInfo *left; /* left input clump */
RelOptInfo *right; /* right input clump */
+ double rows; /* estimated join cardinality */
+ double selectivity; /* join selectivity */
+ double result_size; /* estimated result size in bytes */
Cost total_cost; /* total cost of cheapest path */
} GooCandidate;
@@ -417,6 +421,11 @@ static GooCandidate * goo_build_candidate(GooState * state, RelOptInfo *left,
int saved_rel_len;
struct HTAB *saved_hash;
RelOptInfo *joinrel;
+ double join_rows;
+ double left_rows;
+ double right_rows;
+ double selectivity = 0.0;
+ double result_size;
Cost total_cost;
GooCandidate *cand;
@@ -477,6 +486,14 @@ static GooCandidate * goo_build_candidate(GooState * state, RelOptInfo *left,
set_cheapest(grouped_rel);
}
+ join_rows = joinrel->rows;
+ left_rows = left->rows;
+ right_rows = right->rows;
+
+ if (left_rows > 0 && right_rows > 0)
+ selectivity = join_rows / (left_rows * right_rows);
+
+ result_size = join_rows * joinrel->reltarget->width;
total_cost = joinrel->cheapest_total_path->total_cost;
/*
@@ -495,6 +512,9 @@ static GooCandidate * goo_build_candidate(GooState * state, RelOptInfo *left,
cand = palloc(sizeof(GooCandidate));
cand->left = left;
cand->right = right;
+ cand->rows = join_rows;
+ cand->selectivity = selectivity;
+ cand->result_size = result_size;
cand->total_cost = total_cost;
MemoryContextSwitchTo(oldcxt);
@@ -608,5 +628,19 @@ goo_commit_join(GooState * state, GooCandidate * cand)
static bool
goo_candidate_better(GooCandidate * a, GooCandidate * b)
{
- return (a->total_cost < b->total_cost);
+ switch (goo_greedy_strategy)
+ {
+ case GOO_GREEDY_STRATEGY_ROWS:
+ return a->rows < b->rows;
+
+ case GOO_GREEDY_STRATEGY_SELECTIVITY:
+ return a->selectivity < b->selectivity;
+
+ case GOO_GREEDY_STRATEGY_RESULT_SIZE:
+ return a->result_size < b->result_size;
+
+ case GOO_GREEDY_STRATEGY_COST:
+ default:
+ return a->total_cost < b->total_cost;
+ }
}
diff --git a/src/backend/utils/misc/guc_parameters.dat b/src/backend/utils/misc/guc_parameters.dat
index a8ce31ab8a7..26d72283e7d 100644
--- a/src/backend/utils/misc/guc_parameters.dat
+++ b/src/backend/utils/misc/guc_parameters.dat
@@ -1154,6 +1154,16 @@
max => 'MAX_KILOBYTES',
},
+/* WIP: only for testing */
+{ name => 'goo_greedy_strategy', type => 'enum', context => 'PGC_USERSET', group => 'QUERY_TUNING_GEQO',
+ short_desc => 'Selects the heuristic used by GOO to compare join candidates.',
+ long_desc => 'Valid values are cost, rows, selectivity, and result_size.',
+ flags => 'GUC_EXPLAIN',
+ variable => 'goo_greedy_strategy',
+ boot_val => 'GOO_GREEDY_STRATEGY_COST',
+ options => 'goo_greedy_strategy_options',
+},
+
{ name => 'gss_accept_delegation', type => 'bool', context => 'PGC_SIGHUP', group => 'CONN_AUTH_AUTH',
short_desc => 'Sets whether GSSAPI delegation should be accepted from the client.',
variable => 'pg_gss_accept_delegation',
diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c
index f87b558c2c6..f8812d65294 100644
--- a/src/backend/utils/misc/guc_tables.c
+++ b/src/backend/utils/misc/guc_tables.c
@@ -411,6 +411,14 @@ static const struct config_enum_entry plan_cache_mode_options[] = {
{NULL, 0, false}
};
+static const struct config_enum_entry goo_greedy_strategy_options[] = {
+ {"cost", GOO_GREEDY_STRATEGY_COST, false},
+ {"rows", GOO_GREEDY_STRATEGY_ROWS, false},
+ {"selectivity", GOO_GREEDY_STRATEGY_SELECTIVITY, false},
+ {"result_size", GOO_GREEDY_STRATEGY_RESULT_SIZE, false},
+ {NULL, 0, false}
+};
+
static const struct config_enum_entry password_encryption_options[] = {
{"md5", PASSWORD_TYPE_MD5, false},
{"scram-sha-256", PASSWORD_TYPE_SCRAM_SHA_256, false},
diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h
index 5b3ebe5f1d2..28846d01d3a 100644
--- a/src/include/optimizer/paths.h
+++ b/src/include/optimizer/paths.h
@@ -16,12 +16,20 @@
#include "nodes/pathnodes.h"
+typedef enum GooGreedyStrategy
+{
+ GOO_GREEDY_STRATEGY_COST,
+ GOO_GREEDY_STRATEGY_ROWS,
+ GOO_GREEDY_STRATEGY_SELECTIVITY,
+ GOO_GREEDY_STRATEGY_RESULT_SIZE
+} GooGreedyStrategy;
/*
* allpaths.c
*/
extern PGDLLIMPORT bool enable_geqo;
extern PGDLLIMPORT bool enable_goo_join_search;
+extern PGDLLIMPORT int goo_greedy_strategy;
extern PGDLLIMPORT bool enable_eager_aggregate;
extern PGDLLIMPORT int geqo_threshold;
extern PGDLLIMPORT double min_eager_agg_group_size;
--
2.39.3 (Apple Git-146)