From 5777b1bd17e06fdbc5e8cf55bee6ae38ad623d76 Mon Sep 17 00:00:00 2001 From: Chengpeng Yan 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 --- 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)