1
0
mirror of https://github.com/postgres/postgres.git synced 2025-10-16 17:07:43 +03:00

Remove PlannerInfo's join_search_private method.

Instead, use the new mechanism that allows planner extensions to store
private state inside a PlannerInfo, treating GEQO as an in-core planner
extension.  This is a useful test of the new facility, and also buys
back a few bytes of storage.

To make this work, we must remove innerrel_is_unique_ext's hack of
testing whether join_search_private is set as a proxy for whether
the join search might be retried. Add a flag that extensions can
use to explicitly signal their intentions instead.

Reviewed-by: Andrei Lepikhov <lepihov@gmail.com>
Reviewed-by: Melanie Plageman <melanieplageman@gmail.com>
Reviewed-by: Tom Lane <tgl@sss.pgh.pa.us>
Discussion: http://postgr.es/m/CA+TgmoYWKHU2hKr62Toyzh-kTDEnMDeLw7gkOOnjL-TnOUq0kQ@mail.gmail.com
This commit is contained in:
Robert Haas
2025-08-20 15:10:52 -04:00
parent 0132dddab3
commit 64095d1574
8 changed files with 32 additions and 17 deletions

View File

@@ -162,7 +162,7 @@ geqo_eval(PlannerInfo *root, Gene *tour, int num_gene)
RelOptInfo * RelOptInfo *
gimme_tree(PlannerInfo *root, Gene *tour, int num_gene) gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
{ {
GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; GeqoPrivateData *private = GetGeqoPrivateData(root);
List *clumps; List *clumps;
int rel_count; int rel_count;

View File

@@ -47,6 +47,8 @@ int Geqo_generations;
double Geqo_selection_bias; double Geqo_selection_bias;
double Geqo_seed; double Geqo_seed;
/* GEQO is treated as an in-core planner extension */
int Geqo_planner_extension_id = -1;
static int gimme_pool_size(int nr_rel); static int gimme_pool_size(int nr_rel);
static int gimme_number_generations(int pool_size); static int gimme_number_generations(int pool_size);
@@ -98,10 +100,16 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
int mutations = 0; int mutations = 0;
#endif #endif
if (Geqo_planner_extension_id < 0)
Geqo_planner_extension_id = GetPlannerExtensionId("geqo");
/* set up private information */ /* set up private information */
root->join_search_private = &private; SetPlannerInfoExtensionState(root, Geqo_planner_extension_id, &private);
private.initial_rels = initial_rels; private.initial_rels = initial_rels;
/* inform core planner that we may replan */
root->assumeReplanning = true;
/* initialize private number generator */ /* initialize private number generator */
geqo_set_seed(root, Geqo_seed); geqo_set_seed(root, Geqo_seed);
@@ -304,7 +312,7 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels)
free_pool(root, pool); free_pool(root, pool);
/* ... clear root pointer to our private storage */ /* ... clear root pointer to our private storage */
root->join_search_private = NULL; SetPlannerInfoExtensionState(root, Geqo_planner_extension_id, NULL);
return best_rel; return best_rel;
} }

View File

@@ -15,11 +15,10 @@
#include "optimizer/geqo_random.h" #include "optimizer/geqo_random.h"
void void
geqo_set_seed(PlannerInfo *root, double seed) geqo_set_seed(PlannerInfo *root, double seed)
{ {
GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; GeqoPrivateData *private = GetGeqoPrivateData(root);
pg_prng_fseed(&private->random_state, seed); pg_prng_fseed(&private->random_state, seed);
} }
@@ -27,7 +26,7 @@ geqo_set_seed(PlannerInfo *root, double seed)
double double
geqo_rand(PlannerInfo *root) geqo_rand(PlannerInfo *root)
{ {
GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; GeqoPrivateData *private = GetGeqoPrivateData(root);
return pg_prng_double(&private->random_state); return pg_prng_double(&private->random_state);
} }
@@ -35,7 +34,7 @@ geqo_rand(PlannerInfo *root)
int int
geqo_randint(PlannerInfo *root, int upper, int lower) geqo_randint(PlannerInfo *root, int upper, int lower)
{ {
GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; GeqoPrivateData *private = GetGeqoPrivateData(root);
/* /*
* In current usage, "lower" is never negative so we can just use * In current usage, "lower" is never negative so we can just use

View File

@@ -1425,17 +1425,14 @@ innerrel_is_unique_ext(PlannerInfo *root,
* *
* However, in normal planning mode, caching this knowledge is totally * However, in normal planning mode, caching this knowledge is totally
* pointless; it won't be queried again, because we build up joinrels * pointless; it won't be queried again, because we build up joinrels
* from smaller to larger. It is useful in GEQO mode, where the * from smaller to larger. It's only useful when using GEQO or
* knowledge can be carried across successive planning attempts; and * another planner extension that attempts planning multiple times.
* it's likely to be useful when using join-search plugins, too. Hence
* cache when join_search_private is non-NULL. (Yeah, that's a hack,
* but it seems reasonable.)
* *
* Also, allow callers to override that heuristic and force caching; * Also, allow callers to override that heuristic and force caching;
* that's useful for reduce_unique_semijoins, which calls here before * that's useful for reduce_unique_semijoins, which calls here before
* the normal join search starts. * the normal join search starts.
*/ */
if (force_cache || root->join_search_private) if (force_cache || root->assumeReplanning)
{ {
old_context = MemoryContextSwitchTo(root->planner_cxt); old_context = MemoryContextSwitchTo(root->planner_cxt);
innerrel->non_unique_for_rels = innerrel->non_unique_for_rels =

View File

@@ -706,6 +706,7 @@ subquery_planner(PlannerGlobal *glob, Query *parse, char *plan_name,
root->hasAlternativeSubPlans = false; root->hasAlternativeSubPlans = false;
root->placeholdersFrozen = false; root->placeholdersFrozen = false;
root->hasRecursion = hasRecursion; root->hasRecursion = hasRecursion;
root->assumeReplanning = false;
if (hasRecursion) if (hasRecursion)
root->wt_param_id = assign_special_exec_param(root); root->wt_param_id = assign_special_exec_param(root);
else else

View File

@@ -1384,6 +1384,7 @@ pull_up_simple_subquery(PlannerInfo *root, Node *jtnode, RangeTblEntry *rte,
subroot->qual_security_level = 0; subroot->qual_security_level = 0;
subroot->placeholdersFrozen = false; subroot->placeholdersFrozen = false;
subroot->hasRecursion = false; subroot->hasRecursion = false;
subroot->assumeReplanning = false;
subroot->wt_param_id = -1; subroot->wt_param_id = -1;
subroot->non_recursive_path = NULL; subroot->non_recursive_path = NULL;
/* We don't currently need a top JoinDomain for the subroot */ /* We don't currently need a top JoinDomain for the subroot */

View File

@@ -536,6 +536,8 @@ struct PlannerInfo
bool placeholdersFrozen; bool placeholdersFrozen;
/* true if planning a recursive WITH item */ /* true if planning a recursive WITH item */
bool hasRecursion; bool hasRecursion;
/* true if a planner extension may replan this subquery */
bool assumeReplanning;
/* /*
* The rangetable index for the RTE_GROUP RTE, or 0 if there is no * The rangetable index for the RTE_GROUP RTE, or 0 if there is no
@@ -582,9 +584,6 @@ struct PlannerInfo
bool *isAltSubplan pg_node_attr(read_write_ignore); bool *isAltSubplan pg_node_attr(read_write_ignore);
bool *isUsedSubplan pg_node_attr(read_write_ignore); bool *isUsedSubplan pg_node_attr(read_write_ignore);
/* optional private data for join_search_hook, e.g., GEQO */
void *join_search_private pg_node_attr(read_write_ignore);
/* Does this query modify any partition key columns? */ /* Does this query modify any partition key columns? */
bool partColsUpdated; bool partColsUpdated;

View File

@@ -24,6 +24,7 @@
#include "common/pg_prng.h" #include "common/pg_prng.h"
#include "nodes/pathnodes.h" #include "nodes/pathnodes.h"
#include "optimizer/extendplan.h"
#include "optimizer/geqo_gene.h" #include "optimizer/geqo_gene.h"
@@ -62,6 +63,8 @@ extern PGDLLIMPORT int Geqo_generations; /* 1 .. inf, or 0 to use default */
extern PGDLLIMPORT double Geqo_selection_bias; extern PGDLLIMPORT double Geqo_selection_bias;
extern PGDLLIMPORT int Geqo_planner_extension_id;
#define DEFAULT_GEQO_SELECTION_BIAS 2.0 #define DEFAULT_GEQO_SELECTION_BIAS 2.0
#define MIN_GEQO_SELECTION_BIAS 1.5 #define MIN_GEQO_SELECTION_BIAS 1.5
#define MAX_GEQO_SELECTION_BIAS 2.0 #define MAX_GEQO_SELECTION_BIAS 2.0
@@ -70,7 +73,7 @@ extern PGDLLIMPORT double Geqo_seed; /* 0 .. 1 */
/* /*
* Private state for a GEQO run --- accessible via root->join_search_private * Private state for a GEQO run --- accessible via GetGeqoPrivateData
*/ */
typedef struct typedef struct
{ {
@@ -78,6 +81,13 @@ typedef struct
pg_prng_state random_state; /* PRNG state */ pg_prng_state random_state; /* PRNG state */
} GeqoPrivateData; } GeqoPrivateData;
static inline GeqoPrivateData *
GetGeqoPrivateData(PlannerInfo *root)
{
/* headers must be C++-compliant, so the cast is required here */
return (GeqoPrivateData *)
GetPlannerInfoExtensionState(root, Geqo_planner_extension_id);
}
/* routines in geqo_main.c */ /* routines in geqo_main.c */
extern RelOptInfo *geqo(PlannerInfo *root, extern RelOptInfo *geqo(PlannerInfo *root,