diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 3b527a7ecbd51f034a927b74d70387e85d296264..a86ba6089a49395d072dc5fb99fddfd78569512a 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.221 2009/07/03 19:14:25 petere Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/config.sgml,v 1.222 2009/07/16 20:55:44 tgl Exp $ --> <chapter Id="runtime-config"> <title>Server Configuration</title> @@ -2149,7 +2149,23 @@ archive_command = 'copy "%p" "C:\\server\\archivedir\\%f"' # Windows </para> </listitem> </varlistentry> - + + <varlistentry id="guc-geqo-seed" xreflabel="geqo_seed"> + <term><varname>geqo_seed</varname> (<type>floating point</type>)</term> + <indexterm> + <primary><varname>geqo_seed</> configuration parameter</primary> + </indexterm> + <listitem> + <para> + Controls the initial value of the random number generator used + by GEQO to select random paths through the join order search space. + The value can range from zero (the default) to one. Varying the + value changes the set of join paths explored, and may result in a + better or worse best path being found. + </para> + </listitem> + </varlistentry> + </variablelist> </sect2> <sect2 id="runtime-config-query-other"> diff --git a/doc/src/sgml/geqo.sgml b/doc/src/sgml/geqo.sgml index 2f680762c13bb45c3b85bbba5c43011de112eb4b..97961272a4ae97150f6d1518b34d40523cf25a04 100644 --- a/doc/src/sgml/geqo.sgml +++ b/doc/src/sgml/geqo.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/geqo.sgml,v 1.40 2007/07/21 04:02:41 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/geqo.sgml,v 1.41 2009/07/16 20:55:44 tgl Exp $ --> <chapter id="geqo"> <chapterinfo> @@ -49,7 +49,7 @@ methods</firstterm> (e.g., nested loop, hash join, merge join in <productname>PostgreSQL</productname>) to process individual joins and a diversity of <firstterm>indexes</firstterm> (e.g., - B-tree, hash, GiST and GIN in <productname>PostgreSQL</productname>) as + B-tree, hash, GiST and GIN in <productname>PostgreSQL</productname>) as access paths for relations. </para> @@ -88,8 +88,7 @@ <para> The genetic algorithm (<acronym>GA</acronym>) is a heuristic optimization method which - operates through - nondeterministic, randomized search. The set of possible solutions for the + operates through randomized search. The set of possible solutions for the optimization problem is considered as a <firstterm>population</firstterm> of <firstterm>individuals</firstterm>. The degree of adaptation of an individual to its environment is specified @@ -116,7 +115,7 @@ According to the <systemitem class="resource">comp.ai.genetic</> <acronym>FAQ</acronym> it cannot be stressed too strongly that a <acronym>GA</acronym> is not a pure random search for a solution to a problem. A <acronym>GA</acronym> uses stochastic processes, but the result is distinctly - non-random (better than random). + non-random (better than random). </para> <figure id="geqo-diagram"> @@ -260,9 +259,13 @@ <para> This process is inherently nondeterministic, because of the randomized choices made during both the initial population selection and subsequent - <quote>mutation</> of the best candidates. Hence different plans may - be selected from one run to the next, resulting in varying run time - and varying output row order. + <quote>mutation</> of the best candidates. To avoid surprising changes + of the selected plan, each run of the GEQO algorithm restarts its + random number generator with the current <xref linkend="guc-geqo-seed"> + parameter setting. As long as <varname>geqo_seed</> and the other + GEQO parameters are kept fixed, the same plan will be generated for a + given query (and other planner inputs such as statistics). To experiment + with different search paths, try changing <varname>geqo_seed</>. </para> </sect2> @@ -330,7 +333,7 @@ url="news://comp.ai.genetic"></ulink>) </para> </listitem> - + <listitem> <para> <ulink url="http://www.red3d.com/cwr/evolve.html"> diff --git a/src/backend/optimizer/geqo/Makefile b/src/backend/optimizer/geqo/Makefile index becc95f2ef4378b6fb2bd4f7d231a18c8debfc93..9ccfd9e60c85934e5c1da1494f6cc0864770912d 100644 --- a/src/backend/optimizer/geqo/Makefile +++ b/src/backend/optimizer/geqo/Makefile @@ -5,7 +5,7 @@ # # Copyright (c) 1994, Regents of the University of California # -# $PostgreSQL: pgsql/src/backend/optimizer/geqo/Makefile,v 1.20 2008/02/19 10:30:07 petere Exp $ +# $PostgreSQL: pgsql/src/backend/optimizer/geqo/Makefile,v 1.21 2009/07/16 20:55:44 tgl Exp $ # #------------------------------------------------------------------------- @@ -14,7 +14,7 @@ top_builddir = ../../../.. include $(top_builddir)/src/Makefile.global OBJS = geqo_copy.o geqo_eval.o geqo_main.o geqo_misc.o \ - geqo_mutation.o geqo_pool.o geqo_recombination.o \ + geqo_mutation.o geqo_pool.o geqo_random.o geqo_recombination.o \ geqo_selection.o \ geqo_erx.o geqo_pmx.o geqo_cx.o geqo_px.o geqo_ox1.o geqo_ox2.o diff --git a/src/backend/optimizer/geqo/geqo_copy.c b/src/backend/optimizer/geqo/geqo_copy.c index 8e4aab214d6af73e3dbed04d36afca00de2d247f..1c7498c959ca0b851c036be47f83f7ce9fecd485 100644 --- a/src/backend/optimizer/geqo/geqo_copy.c +++ b/src/backend/optimizer/geqo/geqo_copy.c @@ -5,7 +5,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_copy.c,v 1.19 2009/01/01 17:23:43 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_copy.c,v 1.20 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,7 +42,8 @@ * */ void -geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length) +geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2, + int string_length) { int i; diff --git a/src/backend/optimizer/geqo/geqo_cx.c b/src/backend/optimizer/geqo/geqo_cx.c index 616ff41fb9734fe7a37c419adc943713b37675f0..9f3dfe216e0c49686e9086a3102c21cd25f1fc82 100644 --- a/src/backend/optimizer/geqo/geqo_cx.c +++ b/src/backend/optimizer/geqo/geqo_cx.c @@ -6,7 +6,7 @@ * CX operator according to Oliver et al * (Proc 2nd Int'l Conf on GA's) * -* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_cx.c,v 1.10 2003/11/29 22:39:49 pgsql Exp $ +* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_cx.c,v 1.11 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,7 +44,8 @@ * cycle crossover */ int -cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +cx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, + int num_gene, City *city_table) { int i, @@ -62,7 +63,7 @@ cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) } /* choose random cycle starting position */ - start_pos = geqo_randint(num_gene - 1, 0); + start_pos = geqo_randint(root, num_gene - 1, 0); /* child inherits first city */ offspring[start_pos] = tour1[start_pos]; diff --git a/src/backend/optimizer/geqo/geqo_erx.c b/src/backend/optimizer/geqo/geqo_erx.c index 9c7a34258582d08f421780c7e9ca72bd1de95ff8..45effbdad95c93cc1ddf6800860ee9ddcc15cfec 100644 --- a/src/backend/optimizer/geqo/geqo_erx.c +++ b/src/backend/optimizer/geqo/geqo_erx.c @@ -3,7 +3,7 @@ * geqo_erx.c * edge recombination crossover [ER] * -* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_erx.c,v 1.20 2005/10/15 02:49:19 momjian Exp $ +* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_erx.c,v 1.21 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,11 +36,11 @@ #include "optimizer/geqo_random.h" -static int gimme_edge(Gene gene1, Gene gene2, Edge *edge_table); -static void remove_gene(Gene gene, Edge edge, Edge *edge_table); -static Gene gimme_gene(Edge edge, Edge *edge_table); +static int gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table); +static void remove_gene(PlannerInfo *root, Gene gene, Edge edge, Edge *edge_table); +static Gene gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table); -static Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene); +static Gene edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene); /* alloc_edge_table @@ -50,7 +50,7 @@ static Gene edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene); */ Edge * -alloc_edge_table(int num_gene) +alloc_edge_table(PlannerInfo *root, int num_gene) { Edge *edge_table; @@ -70,7 +70,7 @@ alloc_edge_table(int num_gene) * */ void -free_edge_table(Edge *edge_table) +free_edge_table(PlannerInfo *root, Edge *edge_table) { pfree(edge_table); } @@ -89,7 +89,8 @@ free_edge_table(Edge *edge_table) * */ float -gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table) +gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2, + int num_gene, Edge *edge_table) { int i, index1, @@ -121,11 +122,11 @@ gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table) * twice per edge */ - edge_total += gimme_edge(tour1[index1], tour1[index2], edge_table); - gimme_edge(tour1[index2], tour1[index1], edge_table); + edge_total += gimme_edge(root, tour1[index1], tour1[index2], edge_table); + gimme_edge(root, tour1[index2], tour1[index1], edge_table); - edge_total += gimme_edge(tour2[index1], tour2[index2], edge_table); - gimme_edge(tour2[index2], tour2[index1], edge_table); + edge_total += gimme_edge(root, tour2[index1], tour2[index2], edge_table); + gimme_edge(root, tour2[index2], tour2[index1], edge_table); } /* return average number of edges per index */ @@ -147,7 +148,7 @@ gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table) * 0 if edge was already registered and edge_table is unchanged */ static int -gimme_edge(Gene gene1, Gene gene2, Edge *edge_table) +gimme_edge(PlannerInfo *root, Gene gene1, Gene gene2, Edge *edge_table) { int i; int edges; @@ -189,13 +190,13 @@ gimme_edge(Gene gene1, Gene gene2, Edge *edge_table) * */ int -gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene) +gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, int num_gene) { int i; int edge_failures = 0; - new_gene[0] = (Gene) geqo_randint(num_gene, 1); /* choose int between 1 - * and num_gene */ + /* choose int between 1 and num_gene */ + new_gene[0] = (Gene) geqo_randint(root, num_gene, 1); for (i = 1; i < num_gene; i++) { @@ -204,18 +205,18 @@ gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene) * table */ - remove_gene(new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table); + remove_gene(root, new_gene[i - 1], edge_table[(int) new_gene[i - 1]], edge_table); /* find destination for the newly entered point */ if (edge_table[new_gene[i - 1]].unused_edges > 0) - new_gene[i] = gimme_gene(edge_table[(int) new_gene[i - 1]], edge_table); + new_gene[i] = gimme_gene(root, edge_table[(int) new_gene[i - 1]], edge_table); else { /* cope with fault */ edge_failures++; - new_gene[i] = edge_failure(new_gene, i - 1, edge_table, num_gene); + new_gene[i] = edge_failure(root, new_gene, i - 1, edge_table, num_gene); } /* mark this node as incorporated */ @@ -235,7 +236,7 @@ gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene) * */ static void -remove_gene(Gene gene, Edge edge, Edge *edge_table) +remove_gene(PlannerInfo *root, Gene gene, Edge edge, Edge *edge_table) { int i, j; @@ -277,7 +278,7 @@ remove_gene(Gene gene, Edge edge, Edge *edge_table) * */ static Gene -gimme_gene(Edge edge, Edge *edge_table) +gimme_gene(PlannerInfo *root, Edge edge, Edge *edge_table) { int i; Gene friend; @@ -340,7 +341,7 @@ gimme_gene(Edge edge, Edge *edge_table) /* random decision of the possible candidates to use */ - rand_decision = (int) geqo_randint(minimum_count - 1, 0); + rand_decision = geqo_randint(root, minimum_count - 1, 0); for (i = 0; i < edge.unused_edges; i++) @@ -368,7 +369,7 @@ gimme_gene(Edge edge, Edge *edge_table) * */ static Gene -edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene) +edge_failure(PlannerInfo *root, Gene *gene, int index, Edge *edge_table, int num_gene) { int i; Gene fail_gene = gene[index]; @@ -401,7 +402,7 @@ edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene) if (four_count != 0) { - rand_decision = (int) geqo_randint(four_count - 1, 0); + rand_decision = geqo_randint(root, four_count - 1, 0); for (i = 1; i <= num_gene; i++) { @@ -423,7 +424,7 @@ edge_failure(Gene *gene, int index, Edge *edge_table, int num_gene) else if (remaining_edges != 0) { /* random decision of the gene with remaining edges */ - rand_decision = (int) geqo_randint(remaining_edges - 1, 0); + rand_decision = geqo_randint(root, remaining_edges - 1, 0); for (i = 1; i <= num_gene; i++) { diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c index 392cfc5aa318c399077866a9512701a1330fa168..226d64a94d96a7b36ed6f3ea53ff43159ecf50c6 100644 --- a/src/backend/optimizer/geqo/geqo_eval.c +++ b/src/backend/optimizer/geqo/geqo_eval.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.88 2009/01/01 17:23:43 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.89 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,7 +42,7 @@ static bool desirable_join(PlannerInfo *root, * Returns cost of a query tree as an individual of the population. */ Cost -geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) +geqo_eval(PlannerInfo *root, Gene *tour, int num_gene) { MemoryContext mycontext; MemoryContext oldcxt; @@ -94,13 +94,13 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) * (If we are dealing with enough join rels, which we very likely are, a * new hash table will get built and used locally.) */ - savelength = list_length(evaldata->root->join_rel_list); - savehash = evaldata->root->join_rel_hash; + savelength = list_length(root->join_rel_list); + savehash = root->join_rel_hash; - evaldata->root->join_rel_hash = NULL; + root->join_rel_hash = NULL; /* construct the best path for the given combination of relations */ - joinrel = gimme_tree(tour, num_gene, evaldata); + joinrel = gimme_tree(root, tour, num_gene); /* * compute fitness @@ -117,9 +117,9 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) * Restore join_rel_list to its former state, and put back original * hashtable if any. */ - evaldata->root->join_rel_list = list_truncate(evaldata->root->join_rel_list, - savelength); - evaldata->root->join_rel_hash = savehash; + root->join_rel_list = list_truncate(root->join_rel_list, + savelength); + root->join_rel_hash = savehash; /* release all the memory acquired within gimme_tree */ MemoryContextSwitchTo(oldcxt); @@ -134,7 +134,6 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) * order. * * 'tour' is the proposed join order, of length 'num_gene' - * 'evaldata' contains the context we need * * Returns a new join relation whose cheapest path is the best plan for * this join order. NB: will return NULL if join order is invalid. @@ -153,8 +152,9 @@ geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata) * plans. */ RelOptInfo * -gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) +gimme_tree(PlannerInfo *root, Gene *tour, int num_gene) { + GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; RelOptInfo **stack; int stack_depth; RelOptInfo *joinrel; @@ -193,7 +193,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) /* Get the next input relation and push it */ cur_rel_index = (int) tour[rel_count]; - stack[stack_depth] = (RelOptInfo *) list_nth(evaldata->initial_rels, + stack[stack_depth] = (RelOptInfo *) list_nth(private->initial_rels, cur_rel_index - 1); stack_depth++; @@ -211,7 +211,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) * have exhausted the input, the heuristics can't prevent popping. */ if (rel_count < num_gene - 1 && - !desirable_join(evaldata->root, outer_rel, inner_rel)) + !desirable_join(root, outer_rel, inner_rel)) break; /* @@ -220,7 +220,7 @@ gimme_tree(Gene *tour, int num_gene, GeqoEvalData *evaldata) * root->join_rel_list yet, and so the paths constructed for it * will only include the ones we want. */ - joinrel = make_join_rel(evaldata->root, outer_rel, inner_rel); + joinrel = make_join_rel(root, outer_rel, inner_rel); /* Can't pop stack here if join order is not valid */ if (!joinrel) diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c index 08b5b1a44db23dfc235bce0ceab21d5f459bb3b7..824ae7b610817bc96e73aac1e14049ceb1fb4bc8 100644 --- a/src/backend/optimizer/geqo/geqo_main.c +++ b/src/backend/optimizer/geqo/geqo_main.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.56 2009/01/01 17:23:43 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_main.c,v 1.57 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -27,7 +27,9 @@ #include <math.h> #include "optimizer/geqo_misc.h" +#include "optimizer/geqo_mutation.h" #include "optimizer/geqo_pool.h" +#include "optimizer/geqo_random.h" #include "optimizer/geqo_selection.h" @@ -38,6 +40,7 @@ int Geqo_effort; int Geqo_pool_size; int Geqo_generations; double Geqo_selection_bias; +double Geqo_seed; static int gimme_pool_size(int nr_rel); @@ -63,7 +66,7 @@ static int gimme_number_generations(int pool_size); RelOptInfo * geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) { - GeqoEvalData evaldata; + GeqoPrivateData private; int generation; Chromosome *momma; Chromosome *daddy; @@ -88,9 +91,12 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) int mutations = 0; #endif -/* set up evaldata */ - evaldata.root = root; - evaldata.initial_rels = initial_rels; +/* set up private information */ + root->join_search_private = (void *) &private; + private.initial_rels = initial_rels; + +/* initialize private number generator */ + geqo_set_seed(root, Geqo_seed); /* set GA parameters */ pool_size = gimme_pool_size(number_of_rels); @@ -98,13 +104,13 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) status_interval = 10; /* allocate genetic pool memory */ - pool = alloc_pool(pool_size, number_of_rels); + pool = alloc_pool(root, pool_size, number_of_rels); /* random initialization of the pool */ - random_init_pool(pool, &evaldata); + random_init_pool(root, pool); /* sort the pool according to cheapest path as fitness */ - sort_pool(pool); /* we have to do it only one time, since all + sort_pool(root, pool); /* we have to do it only one time, since all * kids replace the worst individuals in * future (-> geqo_pool.c:spread_chromo ) */ @@ -116,49 +122,49 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) #endif /* allocate chromosome momma and daddy memory */ - momma = alloc_chromo(pool->string_length); - daddy = alloc_chromo(pool->string_length); + momma = alloc_chromo(root, pool->string_length); + daddy = alloc_chromo(root, pool->string_length); #if defined (ERX) #ifdef GEQO_DEBUG elog(DEBUG2, "using edge recombination crossover [ERX]"); #endif /* allocate edge table memory */ - edge_table = alloc_edge_table(pool->string_length); + edge_table = alloc_edge_table(root, pool->string_length); #elif defined(PMX) #ifdef GEQO_DEBUG elog(DEBUG2, "using partially matched crossover [PMX]"); #endif /* allocate chromosome kid memory */ - kid = alloc_chromo(pool->string_length); + kid = alloc_chromo(root, pool->string_length); #elif defined(CX) #ifdef GEQO_DEBUG elog(DEBUG2, "using cycle crossover [CX]"); #endif /* allocate city table memory */ - kid = alloc_chromo(pool->string_length); - city_table = alloc_city_table(pool->string_length); + kid = alloc_chromo(root, pool->string_length); + city_table = alloc_city_table(root, pool->string_length); #elif defined(PX) #ifdef GEQO_DEBUG elog(DEBUG2, "using position crossover [PX]"); #endif /* allocate city table memory */ - kid = alloc_chromo(pool->string_length); - city_table = alloc_city_table(pool->string_length); + kid = alloc_chromo(root, pool->string_length); + city_table = alloc_city_table(root, pool->string_length); #elif defined(OX1) #ifdef GEQO_DEBUG elog(DEBUG2, "using order crossover [OX1]"); #endif /* allocate city table memory */ - kid = alloc_chromo(pool->string_length); - city_table = alloc_city_table(pool->string_length); + kid = alloc_chromo(root, pool->string_length); + city_table = alloc_city_table(root, pool->string_length); #elif defined(OX2) #ifdef GEQO_DEBUG elog(DEBUG2, "using order crossover [OX2]"); #endif /* allocate city table memory */ - kid = alloc_chromo(pool->string_length); - city_table = alloc_city_table(pool->string_length); + kid = alloc_chromo(root, pool->string_length); + city_table = alloc_city_table(root, pool->string_length); #endif @@ -168,45 +174,45 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) for (generation = 0; generation < number_generations; generation++) { /* SELECTION: using linear bias function */ - geqo_selection(momma, daddy, pool, Geqo_selection_bias); + geqo_selection(root, momma, daddy, pool, Geqo_selection_bias); #if defined (ERX) /* EDGE RECOMBINATION CROSSOVER */ - difference = gimme_edge_table(momma->string, daddy->string, pool->string_length, edge_table); + difference = gimme_edge_table(root, momma->string, daddy->string, pool->string_length, edge_table); kid = momma; /* are there any edge failures ? */ - edge_failures += gimme_tour(edge_table, kid->string, pool->string_length); + edge_failures += gimme_tour(root, edge_table, kid->string, pool->string_length); #elif defined(PMX) /* PARTIALLY MATCHED CROSSOVER */ - pmx(momma->string, daddy->string, kid->string, pool->string_length); + pmx(root, momma->string, daddy->string, kid->string, pool->string_length); #elif defined(CX) /* CYCLE CROSSOVER */ - cycle_diffs = cx(momma->string, daddy->string, kid->string, pool->string_length, city_table); + cycle_diffs = cx(root, momma->string, daddy->string, kid->string, pool->string_length, city_table); /* mutate the child */ if (cycle_diffs == 0) { mutations++; - geqo_mutation(kid->string, pool->string_length); + geqo_mutation(root, kid->string, pool->string_length); } #elif defined(PX) /* POSITION CROSSOVER */ - px(momma->string, daddy->string, kid->string, pool->string_length, city_table); + px(root, momma->string, daddy->string, kid->string, pool->string_length, city_table); #elif defined(OX1) /* ORDER CROSSOVER */ - ox1(momma->string, daddy->string, kid->string, pool->string_length, city_table); + ox1(root, momma->string, daddy->string, kid->string, pool->string_length, city_table); #elif defined(OX2) /* ORDER CROSSOVER */ - ox2(momma->string, daddy->string, kid->string, pool->string_length, city_table); + ox2(root, momma->string, daddy->string, kid->string, pool->string_length, city_table); #endif /* EVALUATE FITNESS */ - kid->worth = geqo_eval(kid->string, pool->string_length, &evaldata); + kid->worth = geqo_eval(root, kid->string, pool->string_length); /* push the kid into the wilderness of life according to its worth */ - spread_chromo(kid, pool); + spread_chromo(root, kid, pool); #ifdef GEQO_DEBUG @@ -249,7 +255,7 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) */ best_tour = (Gene *) pool->data[0].string; - best_rel = gimme_tree(best_tour, pool->string_length, &evaldata); + best_rel = gimme_tree(root, best_tour, pool->string_length); if (best_rel == NULL) elog(ERROR, "failed to make a valid plan"); @@ -260,28 +266,31 @@ geqo(PlannerInfo *root, int number_of_rels, List *initial_rels) #endif /* ... free memory stuff */ - free_chromo(momma); - free_chromo(daddy); + free_chromo(root, momma); + free_chromo(root, daddy); #if defined (ERX) - free_edge_table(edge_table); + free_edge_table(root, edge_table); #elif defined(PMX) - free_chromo(kid); + free_chromo(root, kid); #elif defined(CX) - free_chromo(kid); - free_city_table(city_table); + free_chromo(root, kid); + free_city_table(root, city_table); #elif defined(PX) - free_chromo(kid); - free_city_table(city_table); + free_chromo(root, kid); + free_city_table(root, city_table); #elif defined(OX1) - free_chromo(kid); - free_city_table(city_table); + free_chromo(root, kid); + free_city_table(root, city_table); #elif defined(OX2) - free_chromo(kid); - free_city_table(city_table); + free_chromo(root, kid); + free_city_table(root, city_table); #endif - free_pool(pool); + free_pool(root, pool); + + /* ... clear root pointer to our private storage */ + root->join_search_private = NULL; return best_rel; } diff --git a/src/backend/optimizer/geqo/geqo_mutation.c b/src/backend/optimizer/geqo/geqo_mutation.c index 946eb117e3dd3c6653ff4bbae82be822e1a334ed..bd527324f5ac1cd0f688c95b4f220f8d5fc8c5f1 100644 --- a/src/backend/optimizer/geqo/geqo_mutation.c +++ b/src/backend/optimizer/geqo/geqo_mutation.c @@ -4,7 +4,7 @@ * * TSP mutation routines * -* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_mutation.c,v 1.9 2003/11/29 22:39:49 pgsql Exp $ +* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_mutation.c,v 1.10 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,21 +36,21 @@ #include "optimizer/geqo_random.h" void -geqo_mutation(Gene *tour, int num_gene) +geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene) { int swap1; int swap2; - int num_swaps = geqo_randint(num_gene / 3, 0); + int num_swaps = geqo_randint(root, num_gene / 3, 0); Gene temp; while (num_swaps > 0) { - swap1 = geqo_randint(num_gene - 1, 0); - swap2 = geqo_randint(num_gene - 1, 0); + swap1 = geqo_randint(root, num_gene - 1, 0); + swap2 = geqo_randint(root, num_gene - 1, 0); while (swap1 == swap2) - swap2 = geqo_randint(num_gene - 1, 0); + swap2 = geqo_randint(root, num_gene - 1, 0); temp = tour[swap1]; tour[swap1] = tour[swap2]; diff --git a/src/backend/optimizer/geqo/geqo_ox1.c b/src/backend/optimizer/geqo/geqo_ox1.c index 268194e295cbfd888a1ef7f759c45beb943aa8a8..d11d3cd9c396b966094dff7dbc74b7d6705d7c7f 100644 --- a/src/backend/optimizer/geqo/geqo_ox1.c +++ b/src/backend/optimizer/geqo/geqo_ox1.c @@ -6,7 +6,7 @@ * OX1 operator according to Davis * (Proc Int'l Joint Conf on AI) * -* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_ox1.c,v 1.9 2003/11/29 22:39:49 pgsql Exp $ +* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_ox1.c,v 1.10 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,7 +43,8 @@ * position crossover */ void -ox1(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +ox1(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, + City *city_table) { int left, right, @@ -56,8 +57,8 @@ ox1(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) city_table[k].used = 0; /* select portion to copy from tour1 */ - left = geqo_randint(num_gene - 1, 0); - right = geqo_randint(num_gene - 1, 0); + left = geqo_randint(root, num_gene - 1, 0); + right = geqo_randint(root, num_gene - 1, 0); if (left > right) { diff --git a/src/backend/optimizer/geqo/geqo_ox2.c b/src/backend/optimizer/geqo/geqo_ox2.c index 0c31cccae52ba01b07b4c75ac85b9cdbb3edba21..48ed359a630a62f3eb881856fb3e84b28debd92f 100644 --- a/src/backend/optimizer/geqo/geqo_ox2.c +++ b/src/backend/optimizer/geqo/geqo_ox2.c @@ -6,7 +6,7 @@ * OX2 operator according to Syswerda * (The Genetic Algorithms Handbook, ed L Davis) * -* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_ox2.c,v 1.10 2004/10/07 15:21:52 momjian Exp $ +* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_ox2.c,v 1.11 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,7 +43,7 @@ * position crossover */ void -ox2(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +ox2(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) { int k, j, @@ -60,12 +60,12 @@ ox2(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) } /* determine the number of positions to be inherited from tour1 */ - num_positions = geqo_randint(2 * num_gene / 3, num_gene / 3); + num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3); /* make a list of selected cities */ for (k = 0; k < num_positions; k++) { - pos = geqo_randint(num_gene - 1, 0); + pos = geqo_randint(root, num_gene - 1, 0); city_table[pos].select_list = (int) tour1[pos]; city_table[(int) tour1[pos]].used = 1; /* mark used */ } diff --git a/src/backend/optimizer/geqo/geqo_pmx.c b/src/backend/optimizer/geqo/geqo_pmx.c index dc52b731523e4a8054e4e8bcf5374889829ac9b1..a1f3d1019ec87f1e5e576e63012170b8efc56869 100644 --- a/src/backend/optimizer/geqo/geqo_pmx.c +++ b/src/backend/optimizer/geqo/geqo_pmx.c @@ -6,7 +6,7 @@ * PMX operator according to Goldberg & Lingle * (Proc Int'l Conf on GA's) * -* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_pmx.c,v 1.10 2003/11/29 22:39:49 pgsql Exp $ +* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_pmx.c,v 1.11 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,7 +43,7 @@ * partially matched crossover */ void -pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene) +pmx(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene) { int *failed = (int *) palloc((num_gene + 1) * sizeof(int)); int *from = (int *) palloc((num_gene + 1) * sizeof(int)); @@ -71,8 +71,8 @@ pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene) } /* locate crossover points */ - left = geqo_randint(num_gene - 1, 0); - right = geqo_randint(num_gene - 1, 0); + left = geqo_randint(root, num_gene - 1, 0); + right = geqo_randint(root, num_gene - 1, 0); if (left > right) { diff --git a/src/backend/optimizer/geqo/geqo_pool.c b/src/backend/optimizer/geqo/geqo_pool.c index 7562d2ee0b31aa5fdfcd3440d8ee5eae8e620ff9..26137272f70888556a6ce2643750e74651328f57 100644 --- a/src/backend/optimizer/geqo/geqo_pool.c +++ b/src/backend/optimizer/geqo/geqo_pool.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_pool.c,v 1.33 2009/01/01 17:23:43 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_pool.c,v 1.34 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -39,7 +39,7 @@ static int compare(const void *arg1, const void *arg2); * allocates memory for GA pool */ Pool * -alloc_pool(int pool_size, int string_length) +alloc_pool(PlannerInfo *root, int pool_size, int string_length) { Pool *new_pool; Chromosome *chromo; @@ -66,7 +66,7 @@ alloc_pool(int pool_size, int string_length) * deallocates memory for GA pool */ void -free_pool(Pool *pool) +free_pool(PlannerInfo *root, Pool *pool) { Chromosome *chromo; int i; @@ -88,7 +88,7 @@ free_pool(Pool *pool) * initialize genetic pool */ void -random_init_pool(Pool *pool, GeqoEvalData *evaldata) +random_init_pool(PlannerInfo *root, Pool *pool) { Chromosome *chromo = (Chromosome *) pool->data; int i; @@ -105,10 +105,9 @@ random_init_pool(Pool *pool, GeqoEvalData *evaldata) i = 0; while (i < pool->size) { - init_tour(chromo[i].string, pool->string_length); - pool->data[i].worth = geqo_eval(chromo[i].string, - pool->string_length, - evaldata); + init_tour(root, chromo[i].string, pool->string_length); + pool->data[i].worth = geqo_eval(root, chromo[i].string, + pool->string_length); if (pool->data[i].worth < DBL_MAX) i++; else @@ -133,7 +132,7 @@ random_init_pool(Pool *pool, GeqoEvalData *evaldata) * maybe you have to change compare() for different ordering ... */ void -sort_pool(Pool *pool) +sort_pool(PlannerInfo *root, Pool *pool) { qsort(pool->data, pool->size, sizeof(Chromosome), compare); } @@ -160,7 +159,7 @@ compare(const void *arg1, const void *arg2) * allocates a chromosome and string space */ Chromosome * -alloc_chromo(int string_length) +alloc_chromo(PlannerInfo *root, int string_length) { Chromosome *chromo; @@ -174,7 +173,7 @@ alloc_chromo(int string_length) * deallocates a chromosome and string space */ void -free_chromo(Chromosome *chromo) +free_chromo(PlannerInfo *root, Chromosome *chromo) { pfree(chromo->string); pfree(chromo); @@ -185,7 +184,7 @@ free_chromo(Chromosome *chromo) * assumes best->worst = smallest->largest */ void -spread_chromo(Chromosome *chromo, Pool *pool) +spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool) { int top, mid, @@ -247,7 +246,7 @@ spread_chromo(Chromosome *chromo, Pool *pool) * copy new gene into pool storage; always replace worst gene in pool */ - geqo_copy(&pool->data[pool->size - 1], chromo, pool->string_length); + geqo_copy(root, &pool->data[pool->size - 1], chromo, pool->string_length); swap_chromo.string = pool->data[pool->size - 1].string; swap_chromo.worth = pool->data[pool->size - 1].worth; diff --git a/src/backend/optimizer/geqo/geqo_px.c b/src/backend/optimizer/geqo/geqo_px.c index 8b6732b72247604a8fd1279c9aaa566ceab673ba..674529313a2be378536fed4aa28ed4bfc6c37b20 100644 --- a/src/backend/optimizer/geqo/geqo_px.c +++ b/src/backend/optimizer/geqo/geqo_px.c @@ -6,7 +6,7 @@ * PX operator according to Syswerda * (The Genetic Algorithms Handbook, L Davis, ed) * -* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_px.c,v 1.10 2003/11/29 22:39:49 pgsql Exp $ +* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_px.c,v 1.11 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -43,7 +43,8 @@ * position crossover */ void -px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) +px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, + City *city_table) { int num_positions; @@ -57,12 +58,12 @@ px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table) city_table[i].used = 0; /* choose random positions that will be inherited directly from parent */ - num_positions = geqo_randint(2 * num_gene / 3, num_gene / 3); + num_positions = geqo_randint(root, 2 * num_gene / 3, num_gene / 3); /* choose random position */ for (i = 0; i < num_positions; i++) { - pos = geqo_randint(num_gene - 1, 0); + pos = geqo_randint(root, num_gene - 1, 0); offspring[pos] = tour1[pos]; /* transfer cities to child */ city_table[(int) tour1[pos]].used = 1; /* mark city used */ diff --git a/src/backend/optimizer/geqo/geqo_random.c b/src/backend/optimizer/geqo/geqo_random.c new file mode 100644 index 0000000000000000000000000000000000000000..025407e2d3983263401d56af86f1ec97661253a7 --- /dev/null +++ b/src/backend/optimizer/geqo/geqo_random.c @@ -0,0 +1,40 @@ +/*------------------------------------------------------------------------ + * + * geqo_random.c + * random number generator + * + * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group + * Portions Copyright (c) 1994, Regents of the University of California + * + * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_random.c,v 1.1 2009/07/16 20:55:44 tgl Exp $ + * + *------------------------------------------------------------------------- + */ + +#include "postgres.h" + +#include "optimizer/geqo_random.h" + + +void +geqo_set_seed(PlannerInfo *root, double seed) +{ + GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; + + /* + * XXX. This seeding algorithm could certainly be improved - but + * it is not critical to do so. + */ + memset(private->random_state, 0, sizeof(private->random_state)); + memcpy(private->random_state, + &seed, + Min(sizeof(private->random_state), sizeof(seed))); +} + +double +geqo_rand(PlannerInfo *root) +{ + GeqoPrivateData *private = (GeqoPrivateData *) root->join_search_private; + + return erand48(private->random_state); +} diff --git a/src/backend/optimizer/geqo/geqo_recombination.c b/src/backend/optimizer/geqo/geqo_recombination.c index c73e5b2a79e4c3b806e56b462b284e510066ff9e..ebdd220383940e5fff8653cfb2af5250a8556397 100644 --- a/src/backend/optimizer/geqo/geqo_recombination.c +++ b/src/backend/optimizer/geqo/geqo_recombination.c @@ -3,7 +3,7 @@ * geqo_recombination.c * misc recombination procedures * -* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_recombination.c,v 1.15 2005/10/15 02:49:19 momjian Exp $ +* $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_recombination.c,v 1.16 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -35,7 +35,7 @@ * and the procedure repeated. */ void -init_tour(Gene *tour, int num_gene) +init_tour(PlannerInfo *root, Gene *tour, int num_gene) { Gene *tmp; int remainder; @@ -53,7 +53,7 @@ init_tour(Gene *tour, int num_gene) for (i = 0; i < num_gene; i++) { /* choose value between 0 and remainder inclusive */ - next = (int) geqo_randint(remainder, 0); + next = geqo_randint(root, remainder, 0); /* output that element of the tmp array */ tour[i] = tmp[next]; /* and delete it */ @@ -81,7 +81,7 @@ init_tour(Gene *tour, int num_gene) * allocate memory for city table */ City * -alloc_city_table(int num_gene) +alloc_city_table(PlannerInfo *root, int num_gene) { City *city_table; @@ -99,7 +99,7 @@ alloc_city_table(int num_gene) * deallocate memory of city table */ void -free_city_table(City *city_table) +free_city_table(PlannerInfo *root, City *city_table) { pfree(city_table); } diff --git a/src/backend/optimizer/geqo/geqo_selection.c b/src/backend/optimizer/geqo/geqo_selection.c index 3febca3c36fb62c847a96cee5052ca606b411d0d..0ba8941c22e05818bc5c36dc28f18299cf0f2aa3 100644 --- a/src/backend/optimizer/geqo/geqo_selection.c +++ b/src/backend/optimizer/geqo/geqo_selection.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_selection.c,v 1.24 2009/01/01 17:23:43 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/optimizer/geqo/geqo_selection.c,v 1.25 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -42,7 +42,7 @@ #include "optimizer/geqo_random.h" #include "optimizer/geqo_selection.h" -static int linear(int max, double bias); +static int linear(PlannerInfo *root, int max, double bias); /* @@ -51,22 +51,23 @@ static int linear(int max, double bias); * first and second genes are selected from the pool */ void -geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias) +geqo_selection(PlannerInfo *root, Chromosome *momma, Chromosome *daddy, + Pool *pool, double bias) { int first, second; - first = linear(pool->size, bias); - second = linear(pool->size, bias); + first = linear(root, pool->size, bias); + second = linear(root, pool->size, bias); if (pool->size > 1) { while (first == second) - second = linear(pool->size, bias); + second = linear(root, pool->size, bias); } - geqo_copy(momma, &pool->data[first], pool->string_length); - geqo_copy(daddy, &pool->data[second], pool->string_length); + geqo_copy(root, momma, &pool->data[first], pool->string_length); + geqo_copy(root, daddy, &pool->data[second], pool->string_length); } /* @@ -74,12 +75,13 @@ geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias) * generates random integer between 0 and input max number * using input linear bias * + * bias is y-intercept of linear distribution + * * probability distribution function is: f(x) = bias - 2(bias - 1)x * bias = (prob of first rule) / (prob of middle rule) */ static int -linear(int pool_size, double bias) /* bias is y-intercept of linear - * distribution */ +linear(PlannerInfo *root, int pool_size, double bias) { double index; /* index between 0 and pop_size */ double max = (double) pool_size; @@ -95,7 +97,7 @@ linear(int pool_size, double bias) /* bias is y-intercept of linear { double sqrtval; - sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand(); + sqrtval = (bias * bias) - 4.0 * (bias - 1.0) * geqo_rand(root); if (sqrtval > 0.0) sqrtval = sqrt(sqrtval); index = max * (bias - sqrtval) / 2.0 / (bias - 1.0); diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index 2944249a6924e349f43b2a2b2438bddafc0e9155..f3b42da99b15de7284ec901f1835ad437d64aba2 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -10,7 +10,7 @@ * Written by Peter Eisentraut <peter_e@gmx.net>. * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.507 2009/07/16 06:33:44 petere Exp $ + * $PostgreSQL: pgsql/src/backend/utils/misc/guc.c,v 1.508 2009/07/16 20:55:44 tgl Exp $ * *-------------------------------------------------------------------- */ @@ -2026,6 +2026,14 @@ static struct config_real ConfigureNamesReal[] = DEFAULT_GEQO_SELECTION_BIAS, MIN_GEQO_SELECTION_BIAS, MAX_GEQO_SELECTION_BIAS, NULL, NULL }, + { + {"geqo_seed", PGC_USERSET, QUERY_TUNING_GEQO, + gettext_noop("GEQO: seed for random path selection."), + NULL + }, + &Geqo_seed, + 0.0, 0.0, 1.0, NULL, NULL + }, { {"bgwriter_lru_multiplier", PGC_SIGHUP, RESOURCES, diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index c1b888c0d4663088fbd3f40f6949316a5583c13f..e50d7a44f7b839d101ed1384fb1f0ce4972de7d5 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -213,6 +213,7 @@ #geqo_pool_size = 0 # selects default based on effort #geqo_generations = 0 # selects default based on effort #geqo_selection_bias = 2.0 # range 1.5-2.0 +#geqo_seed = 0.0 # range 0.0-1.0 # - Other Planner Options - diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 7eb15dbeecd74b88e94f30c19c649795ca6b610e..4432252a72f3abf47bb3c270e8f259fa830f162a 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.173 2009/06/11 14:49:11 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.174 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -192,6 +192,9 @@ typedef struct PlannerInfo /* These fields are used only when hasRecursion is true: */ int wt_param_id; /* PARAM_EXEC ID for the work table */ struct Plan *non_recursive_plan; /* plan for non-recursive term */ + + /* optional private data for join_search_hook, e.g., GEQO */ + void *join_search_private; } PlannerInfo; diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h index fc06006fd3b4ec5afffec345d38943ba573ea9c1..39226a7c7c98690037016d6c9d3c800c9a90cfa6 100644 --- a/src/include/optimizer/geqo.h +++ b/src/include/optimizer/geqo.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/geqo.h,v 1.44 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/geqo.h,v 1.45 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,7 +46,7 @@ /* * Configuration options * - * If you change these, update backend/utils/misc/postgresql.sample.conf + * If you change these, update backend/utils/misc/postgresql.conf.sample */ extern int Geqo_effort; /* 1 .. 10, knob for adjustment of defaults */ @@ -64,16 +64,17 @@ extern double Geqo_selection_bias; #define MIN_GEQO_SELECTION_BIAS 1.5 #define MAX_GEQO_SELECTION_BIAS 2.0 +extern double Geqo_seed; /* 0 .. 1 */ + /* - * Data structure to encapsulate information needed for building plan trees - * (i.e., geqo_eval and gimme_tree). + * Private state for a GEQO run --- accessible via root->join_search_private */ typedef struct { - PlannerInfo *root; /* the query we are planning */ - List *initial_rels; /* the base relations */ -} GeqoEvalData; + List *initial_rels; /* the base relations we are joining */ + unsigned short random_state[3]; /* state for erand48() */ +} GeqoPrivateData; /* routines in geqo_main.c */ @@ -81,8 +82,7 @@ extern RelOptInfo *geqo(PlannerInfo *root, int number_of_rels, List *initial_rels); /* routines in geqo_eval.c */ -extern Cost geqo_eval(Gene *tour, int num_gene, GeqoEvalData *evaldata); -extern RelOptInfo *gimme_tree(Gene *tour, int num_gene, - GeqoEvalData *evaldata); +extern Cost geqo_eval(PlannerInfo *root, Gene *tour, int num_gene); +extern RelOptInfo *gimme_tree(PlannerInfo *root, Gene *tour, int num_gene); #endif /* GEQO_H */ diff --git a/src/include/optimizer/geqo_copy.h b/src/include/optimizer/geqo_copy.h index 53293c4916114ee4fc2a77923c01b6c5b0fd47a5..582de22e6c3395487b3ef9296b7480fc1418935d 100644 --- a/src/include/optimizer/geqo_copy.h +++ b/src/include/optimizer/geqo_copy.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/geqo_copy.h,v 1.21 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/geqo_copy.h,v 1.22 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,8 +22,9 @@ #ifndef GEQO_COPY_H #define GEQO_COPY_H -#include "optimizer/geqo_gene.h" +#include "optimizer/geqo.h" -extern void geqo_copy(Chromosome *chromo1, Chromosome *chromo2, int string_length); + +extern void geqo_copy(PlannerInfo *root, Chromosome *chromo1, Chromosome *chromo2, int string_length); #endif /* GEQO_COPY_H */ diff --git a/src/include/optimizer/geqo_mutation.h b/src/include/optimizer/geqo_mutation.h index 430797c3707cef28c5787afe134dddea1e42afe5..559c35218db8f4608b97d1a0af666eebfd34b4be 100644 --- a/src/include/optimizer/geqo_mutation.h +++ b/src/include/optimizer/geqo_mutation.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/geqo_mutation.h,v 1.21 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/geqo_mutation.h,v 1.22 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,8 +22,9 @@ #ifndef GEQO_MUTATION_H #define GEQO_MUTATION_H -#include "optimizer/geqo_gene.h" +#include "optimizer/geqo.h" -extern void geqo_mutation(Gene *tour, int num_gene); + +extern void geqo_mutation(PlannerInfo *root, Gene *tour, int num_gene); #endif /* GEQO_MUTATION_H */ diff --git a/src/include/optimizer/geqo_pool.h b/src/include/optimizer/geqo_pool.h index 282b2c2c5b73c27992d67a414f64ff2ec45be302..277b144ebd06a1e1da070e28835f1450487713d1 100644 --- a/src/include/optimizer/geqo_pool.h +++ b/src/include/optimizer/geqo_pool.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/geqo_pool.h,v 1.25 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/geqo_pool.h,v 1.26 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,15 +26,15 @@ #include "optimizer/geqo.h" -extern Pool *alloc_pool(int pool_size, int string_length); -extern void free_pool(Pool *pool); +extern Pool *alloc_pool(PlannerInfo *root, int pool_size, int string_length); +extern void free_pool(PlannerInfo *root, Pool *pool); -extern void random_init_pool(Pool *pool, GeqoEvalData *evaldata); -extern Chromosome *alloc_chromo(int string_length); -extern void free_chromo(Chromosome *chromo); +extern void random_init_pool(PlannerInfo *root, Pool *pool); +extern Chromosome *alloc_chromo(PlannerInfo *root, int string_length); +extern void free_chromo(PlannerInfo *root, Chromosome *chromo); -extern void spread_chromo(Chromosome *chromo, Pool *pool); +extern void spread_chromo(PlannerInfo *root, Chromosome *chromo, Pool *pool); -extern void sort_pool(Pool *pool); +extern void sort_pool(PlannerInfo *root, Pool *pool); #endif /* GEQO_POOL_H */ diff --git a/src/include/optimizer/geqo_random.h b/src/include/optimizer/geqo_random.h index 327989b5fb8bdba91e22bfd264255833ba4abdf5..cb1f60fa34e9b9706d00d58aac4db850c9169334 100644 --- a/src/include/optimizer/geqo_random.h +++ b/src/include/optimizer/geqo_random.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/geqo_random.h,v 1.21 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/geqo_random.h,v 1.22 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,13 +26,16 @@ #include <math.h> -/* geqo_rand returns a random float value between 0 and 1 inclusive */ +#include "optimizer/geqo.h" -#define geqo_rand() ((double) random() / (double) MAX_RANDOM_VALUE) -/* geqo_randint returns integer value between lower and upper inclusive */ +extern void geqo_set_seed(PlannerInfo *root, double seed); -#define geqo_randint(upper,lower) \ - ( (int) floor( geqo_rand()*(((upper)-(lower))+0.999999) ) + (lower) ) +/* geqo_rand returns a random float value between 0 and 1 inclusive */ +extern double geqo_rand(PlannerInfo *root); + +/* geqo_randint returns integer value between lower and upper inclusive */ +#define geqo_randint(root, upper, lower) \ + ( (int) floor( geqo_rand(root)*(((upper)-(lower))+0.999999) ) + (lower) ) #endif /* GEQO_RANDOM_H */ diff --git a/src/include/optimizer/geqo_recombination.h b/src/include/optimizer/geqo_recombination.h index 264560f1128f5f1d08f1fd9dfaf039e7f9c0f7df..456783865065d9440577afa458ccfc64c13d37e7 100644 --- a/src/include/optimizer/geqo_recombination.h +++ b/src/include/optimizer/geqo_recombination.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/geqo_recombination.h,v 1.20 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/geqo_recombination.h,v 1.21 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -24,9 +24,10 @@ #ifndef GEQO_RECOMBINATION_H #define GEQO_RECOMBINATION_H -#include "optimizer/geqo_gene.h" +#include "optimizer/geqo.h" -extern void init_tour(Gene *tour, int num_gene); + +extern void init_tour(PlannerInfo *root, Gene *tour, int num_gene); /* edge recombination crossover [ERX] */ @@ -38,12 +39,14 @@ typedef struct Edge int unused_edges; } Edge; -extern Edge *alloc_edge_table(int num_gene); -extern void free_edge_table(Edge *edge_table); +extern Edge *alloc_edge_table(PlannerInfo *root, int num_gene); +extern void free_edge_table(PlannerInfo *root, Edge *edge_table); -extern float gimme_edge_table(Gene *tour1, Gene *tour2, int num_gene, Edge *edge_table); +extern float gimme_edge_table(PlannerInfo *root, Gene *tour1, Gene *tour2, + int num_gene, Edge *edge_table); -extern int gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene); +extern int gimme_tour(PlannerInfo *root, Edge *edge_table, Gene *new_gene, + int num_gene); /* partially matched crossover [PMX] */ @@ -51,7 +54,9 @@ extern int gimme_tour(Edge *edge_table, Gene *new_gene, int num_gene); #define DAD 1 /* indicator for gene from dad */ #define MOM 0 /* indicator for gene from mom */ -extern void pmx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene); +extern void pmx(PlannerInfo *root, + Gene *tour1, Gene *tour2, + Gene *offspring, int num_gene); typedef struct City @@ -62,19 +67,23 @@ typedef struct City int select_list; } City; -extern City *alloc_city_table(int num_gene); -extern void free_city_table(City *city_table); +extern City *alloc_city_table(PlannerInfo *root, int num_gene); +extern void free_city_table(PlannerInfo *root, City *city_table); /* cycle crossover [CX] */ -extern int cx(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table); +extern int cx(PlannerInfo *root, Gene *tour1, Gene *tour2, + Gene *offspring, int num_gene, City *city_table); /* position crossover [PX] */ -extern void px(Gene *tour1, Gene *tour2, Gene *offspring, int num_gene, City *city_table); +extern void px(PlannerInfo *root, Gene *tour1, Gene *tour2, Gene *offspring, + int num_gene, City *city_table); /* order crossover [OX1] according to Davis */ -extern void ox1(Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table); +extern void ox1(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring, + int num_gene, City *city_table); /* order crossover [OX2] according to Syswerda */ -extern void ox2(Gene *mom, Gene *dad, Gene *offspring, int num_gene, City *city_table); +extern void ox2(PlannerInfo *root, Gene *mom, Gene *dad, Gene *offspring, + int num_gene, City *city_table); #endif /* GEQO_RECOMBINATION_H */ diff --git a/src/include/optimizer/geqo_selection.h b/src/include/optimizer/geqo_selection.h index e37a92b554efba81b586a94888b3f220957204c1..166ba475350cc1c706c6b7c7d61cb0af0c6b0bc7 100644 --- a/src/include/optimizer/geqo_selection.h +++ b/src/include/optimizer/geqo_selection.h @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/optimizer/geqo_selection.h,v 1.21 2009/01/01 17:24:00 momjian Exp $ + * $PostgreSQL: pgsql/src/include/optimizer/geqo_selection.h,v 1.22 2009/07/16 20:55:44 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,8 +23,11 @@ #ifndef GEQO_SELECTION_H #define GEQO_SELECTION_H -#include "optimizer/geqo_gene.h" +#include "optimizer/geqo.h" -extern void geqo_selection(Chromosome *momma, Chromosome *daddy, Pool *pool, double bias); + +extern void geqo_selection(PlannerInfo *root, + Chromosome *momma, Chromosome *daddy, + Pool *pool, double bias); #endif /* GEQO_SELECTION_H */