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:
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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 =
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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,
|
||||
|
Reference in New Issue
Block a user