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 *
gimme_tree(PlannerInfo *root, Gene *tour, int num_gene)
{
GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private;
GeqoPrivateData *private = GetGeqoPrivateData(root);
List *clumps;
int rel_count;

View File

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

View File

@@ -15,11 +15,10 @@
#include "optimizer/geqo_random.h"
void
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);
}
@@ -27,7 +26,7 @@ geqo_set_seed(PlannerInfo *root, double seed)
double
geqo_rand(PlannerInfo *root)
{
GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private;
GeqoPrivateData *private = GetGeqoPrivateData(root);
return pg_prng_double(&private->random_state);
}
@@ -35,7 +34,7 @@ geqo_rand(PlannerInfo *root)
int
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

View File

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

View File

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

View File

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

View File

@@ -536,6 +536,8 @@ struct PlannerInfo
bool placeholdersFrozen;
/* true if planning a recursive WITH item */
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
@@ -582,9 +584,6 @@ struct PlannerInfo
bool *isAltSubplan 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? */
bool partColsUpdated;

View File

@@ -24,6 +24,7 @@
#include "common/pg_prng.h"
#include "nodes/pathnodes.h"
#include "optimizer/extendplan.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 int Geqo_planner_extension_id;
#define DEFAULT_GEQO_SELECTION_BIAS 2.0
#define MIN_GEQO_SELECTION_BIAS 1.5
#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
{
@@ -78,6 +81,13 @@ typedef struct
pg_prng_state random_state; /* PRNG state */
} 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 */
extern RelOptInfo *geqo(PlannerInfo *root,