1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

Remove duplicate geqo functions, and more optimizer cleanup

This commit is contained in:
Bruce Momjian
1999-02-15 03:22:37 +00:00
parent 944d3c395e
commit ba2883b264
26 changed files with 188 additions and 810 deletions

View File

@@ -5,7 +5,7 @@
#
# Copyright (c) 1994, Regents of the University of California
#
# $Id: Makefile,v 1.10 1998/04/06 00:23:07 momjian Exp $
# $Id: Makefile,v 1.11 1999/02/15 03:22:00 momjian Exp $
#
#-------------------------------------------------------------------------
@@ -19,7 +19,7 @@ CFLAGS+= -Wno-error
endif
OBJS = geqo_copy.o geqo_eval.o geqo_main.o geqo_misc.o \
geqo_params.o geqo_paths.o geqo_pool.o geqo_recombination.o \
geqo_params.o geqo_pool.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

View File

@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: geqo_eval.c,v 1.31 1999/02/15 02:04:58 tgl Exp $
* $Id: geqo_eval.c,v 1.32 1999/02/15 03:22:00 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -47,15 +47,7 @@
#include "optimizer/geqo_gene.h"
#include "optimizer/geqo.h"
#include "optimizer/geqo_paths.h"
static List *gimme_clause_joins(Query *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel);
static RelOptInfo *gimme_clauseless_join(RelOptInfo *outer_rel, RelOptInfo *inner_rel);
static RelOptInfo *init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo);
static List *new_join_tlist(List *tlist, List *other_relids, int first_resdomno);
static List *new_joininfo_list(List *joininfo_list, List *join_relids);
static void geqo_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel);
static RelOptInfo *geqo_nth(int stop, List *rels);
/*
@@ -123,15 +115,18 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out
}
else
{ /* tree main part */
if (!(new_rels = gimme_clause_joins(root, outer_rel, inner_rel)))
if (!(new_rels = make_rels_by_clause_joins(root, outer_rel,
inner_rel->joininfo,
inner_rel->relids)))
{
#ifdef NOT_USED
if (BushyPlanFlag)
{
new_rels = lcons(gimme_clauseless_join(outer_rel, outer_rel), NIL); /* ??? MAU */
}
new_rels = make_rels_by_clauseless_joins(outer_rel,
lcons(outer_rel,NIL));
else
new_rels = lcons(gimme_clauseless_join(outer_rel, inner_rel), NIL);
#endif
new_rels = make_rels_by_clauseless_joins(outer_rel,
lcons(inner_rel,NIL));
}
/* process new_rel->pathlist */
@@ -150,7 +145,7 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out
* not possible
*/
if (length(new_rels) > 1)
new_rels = geqo_prune_rels(new_rels);
merge_rels_with_same_relids(new_rels);
if (length(new_rels) > 1)
{ /* should never be reached ... */
@@ -161,7 +156,7 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out
new_rel = (RelOptInfo *) lfirst(new_rels);
rel_count++;
geqo_set_cheapest(new_rel);
set_cheapest(new_rel, new_rel->pathlist);
/* processing of other new_rel attributes */
if (new_rel->size <= 0)
@@ -178,526 +173,6 @@ gimme_tree(Query *root, Gene *tour, int rel_count, int num_gene, RelOptInfo *out
return outer_rel; /* tree finished ... */
}
/*
* gimme_clause_joins
*
* 'outer_rel' is the relation entry for the outer relation
* 'inner_rel' is the relation entry for the inner relation
*
* Returns a list of new join relations.
*/
static List *
gimme_clause_joins(Query *root, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
{
List *join_list = NIL;
List *i = NIL;
List *joininfo_list = (List *) outer_rel->joininfo;
foreach(i, joininfo_list)
{
JoinInfo *joininfo = (JoinInfo *) lfirst(i);
RelOptInfo *rel = NULL;
if (!joininfo->inactive)
{
List *other_rels = (List *) joininfo->otherrels;
if (other_rels != NIL)
{
if ((length(other_rels) == 1))
{
if (same(other_rels, inner_rel->relids))
{ /* look if inner_rel is it... */
rel = init_join_rel(outer_rel, inner_rel, joininfo);
}
}
else if (BushyPlanFlag)
{ /* ?!? MAU */
rel = init_join_rel(outer_rel, get_join_rel(root, other_rels), joininfo);
}
else
rel = NULL;
if (rel != NULL)
join_list = lappend(join_list, rel);
}
}
}
return join_list;
}
/*
* gimme_clauseless_join
* Given an outer relation 'outer_rel' and an inner relation
* 'inner_rel', create a join relation between 'outer_rel' and 'inner_rel'
*
* Returns a new join relation.
*/
static RelOptInfo *
gimme_clauseless_join(RelOptInfo *outer_rel, RelOptInfo *inner_rel)
{
return init_join_rel(outer_rel, inner_rel, (JoinInfo *) NULL);
}
/*
* init_join_rel
* Creates and initializes a new join relation.
*
* 'outer_rel' and 'inner_rel' are relation nodes for the relations to be
* joined
* 'joininfo' is the joininfo node(join clause) containing both
* 'outer_rel' and 'inner_rel', if any exists
*
* Returns the new join relation node.
*/
static RelOptInfo *
init_join_rel(RelOptInfo *outer_rel, RelOptInfo *inner_rel, JoinInfo * joininfo)
{
RelOptInfo *joinrel = makeNode(RelOptInfo);
List *joinrel_joininfo_list = NIL;
List *new_outer_tlist;
List *new_inner_tlist;
/*
* Create a new tlist by removing irrelevant elements from both tlists
* of the outer and inner join relations and then merging the results
* together.
*/
new_outer_tlist = new_join_tlist(outer_rel->targetlist, /* XXX 1-based attnos */
inner_rel->relids, 1);
new_inner_tlist = new_join_tlist(inner_rel->targetlist, /* XXX 1-based attnos */
outer_rel->relids,
length(new_outer_tlist) + 1);
joinrel->relids = NIL;
joinrel->indexed = false;
joinrel->pages = 0;
joinrel->tuples = 0;
joinrel->width = 0;
/* joinrel->targetlist = NIL;*/
joinrel->pathlist = NIL;
joinrel->cheapestpath = (Path *) NULL;
joinrel->pruneable = true;
joinrel->classlist = NULL;
joinrel->relam = InvalidOid;
joinrel->ordering = NULL;
joinrel->restrictinfo = NIL;
joinrel->joininfo = NULL;
joinrel->innerjoin = NIL;
joinrel->superrels = NIL;
joinrel->relids = lcons(outer_rel->relids, lcons(inner_rel->relids, NIL));
new_outer_tlist = nconc(new_outer_tlist, new_inner_tlist);
joinrel->targetlist = new_outer_tlist;
if (joininfo)
{
joinrel->restrictinfo = joininfo->jinfo_restrictinfo;
if (BushyPlanFlag)
joininfo->inactive = true;
}
joinrel_joininfo_list =
new_joininfo_list(append(outer_rel->joininfo, inner_rel->joininfo),
intAppend(outer_rel->relids, inner_rel->relids));
joinrel->joininfo = joinrel_joininfo_list;
geqo_joinrel_size(joinrel, outer_rel, inner_rel);
return joinrel;
}
/*
* new_join_tlist
* Builds a join relations's target list by keeping those elements that
* will be in the final target list and any other elements that are still
* needed for future joins. For a target list entry to still be needed
* for future joins, its 'joinlist' field must not be empty after removal
* of all relids in 'other_relids'.
*
* 'tlist' is the target list of one of the join relations
* 'other_relids' is a list of relids contained within the other
* join relation
* 'first_resdomno' is the resdom number to use for the first created
* target list entry
*
* Returns the new target list.
*/
static List *
new_join_tlist(List *tlist,
List *other_relids,
int first_resdomno)
{
int resdomno = first_resdomno - 1;
TargetEntry *xtl = NULL;
List *t_list = NIL;
List *i = NIL;
List *join_list = NIL;
bool in_final_tlist = false;
foreach(i, tlist)
{
xtl = lfirst(i);
/* XXX surely this is wrong? join_list is never changed? tgl 2/99 */
in_final_tlist = (join_list == NIL);
if (in_final_tlist)
{
resdomno += 1;
t_list = lappend(t_list,
create_tl_element(get_expr(xtl), resdomno));
}
}
return t_list;
}
/*
* new_joininfo_list
* Builds a join relation's joininfo list by checking for join clauses
* which still need to used in future joins involving this relation. A
* join clause is still needed if there are still relations in the clause
* not contained in the list of relations comprising this join relation.
* New joininfo nodes are only created and added to
* 'current_joininfo_list' if a node for a particular join hasn't already
* been created.
*
* 'current_joininfo_list' contains a list of those joininfo nodes that
* have already been built
* 'joininfo_list' is the list of join clauses involving this relation
* 'join_relids' is a list of relids corresponding to the relations
* currently being joined
*
* Returns a list of joininfo nodes, new and old.
*/
static List *
new_joininfo_list(List *joininfo_list, List *join_relids)
{
List *current_joininfo_list = NIL;
List *new_otherrels = NIL;
JoinInfo *other_joininfo = (JoinInfo *) NULL;
List *xjoininfo = NIL;
foreach(xjoininfo, joininfo_list)
{
List *or;
JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo);
new_otherrels = joininfo->otherrels;
foreach(or, new_otherrels)
{
if (intMember(lfirsti(or), join_relids))
new_otherrels = lremove((void *) lfirst(or), new_otherrels);
}
joininfo->otherrels = new_otherrels;
if (new_otherrels != NIL)
{
other_joininfo = joininfo_member(new_otherrels,
current_joininfo_list);
if (other_joininfo)
{
other_joininfo->jinfo_restrictinfo =
(List *) LispUnion(joininfo->jinfo_restrictinfo,
other_joininfo->jinfo_restrictinfo);
}
else
{
other_joininfo = makeNode(JoinInfo);
other_joininfo->otherrels = joininfo->otherrels;
other_joininfo->jinfo_restrictinfo = joininfo->jinfo_restrictinfo;
other_joininfo->mergejoinable = joininfo->mergejoinable;
other_joininfo->hashjoinable = joininfo->hashjoinable;
other_joininfo->inactive = false;
current_joininfo_list = lcons(other_joininfo,
current_joininfo_list);
}
}
}
return current_joininfo_list;
}
#ifdef NOTUSED
/*
* add_new_joininfos
* For each new join relation, create new joininfos that
* use the join relation as inner relation, and add
* the new joininfos to those rel nodes that still
* have joins with the join relation.
*
* 'joinrels' is a list of join relations.
*
* Modifies the joininfo field of appropriate rel nodes.
*/
static void
geqo_add_new_joininfos(Query *root, List *joinrels, List *outerrels)
{
List *xjoinrel = NIL;
List *xrelid = NIL;
List *xrel = NIL;
List *xjoininfo = NIL;
RelOptInfo *rel;
List *relids;
List *super_rels;
List *xsuper_rel = NIL;
JoinInfo *new_joininfo;
foreach(xjoinrel, joinrels)
{
RelOptInfo *joinrel = (RelOptInfo *) lfirst(xjoinrel);
foreach(xrelid, joinrel->relids)
{
/*
* length(joinrel->relids) should always be greater that 1,
* because of *JOIN*
*/
/*
* ! BUG BUG ! Relid relid = (Relid)lfirst(xrelid); RelOptInfo
* *rel = get_join_rel(root, relid);
*/
/*
* if ( (root->join_rel_list) != NIL ) { rel =
* get_join_rel(root, xrelid); } else { rel =
* get_base_rel(root, lfirsti(xrelid)); }
*/
/* NOTE: STILL BUGGY FOR CLAUSE-JOINS: */
/*
* relids = lconsi(lfirsti(xrelid), NIL); rel =
* rel_member(relids, outerrels);
*/
relids = lconsi(lfirsti(xrelid), NIL);
rel = rel_member(relids, root->base_rel_list);
add_superrels(rel, joinrel);
}
}
foreach(xjoinrel, joinrels)
{
RelOptInfo *joinrel = (RelOptInfo *) lfirst(xjoinrel);
foreach(xjoininfo, joinrel->joininfo)
{
JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo);
List *other_rels = joininfo->otherrels;
List *restrict_info = joininfo->jinfo_restrictinfo;
bool mergejoinable = joininfo->mergejoinable;
bool hashjoinable = joininfo->hashjoinable;
foreach(xrelid, other_rels)
{
/*
* ! BUG BUG ! Relid relid = (Relid)lfirst(xrelid);
* RelOptInfo *rel = get_join_rel(root, relid);
*/
/*
* if ( (root->join_rel_list) != NIL ) { rel =
* get_join_rel(root, xrelid); } else { rel =
* get_base_rel(root, lfirsti(xrelid)); }
*/
/* NOTE: STILL BUGGY FOR CLAUSE-JOINS: */
/*
* relids = lconsi(lfirsti(xrelid), NIL); rel =
* rel_member(relids, outerrels);
*/
relids = lconsi(lfirsti(xrelid), NIL);
rel = rel_member(relids, root->base_rel_list);
super_rels = rel->superrels;
new_joininfo = makeNode(JoinInfo);
new_joininfo->otherrels = joinrel->relids;
new_joininfo->jinfo_restrictinfo = restrict_info;
new_joininfo->mergejoinable = mergejoinable;
new_joininfo->hashjoinable = hashjoinable;
new_joininfo->inactive = false;
rel->joininfo = lappend(rel->joininfo, new_joininfo);
foreach(xsuper_rel, super_rels)
{
RelOptInfo *super_rel = (RelOptInfo *) lfirst(xsuper_rel);
if (nonoverlap_rels(super_rel, joinrel))
{
List *new_relids = super_rel->relids;
JoinInfo *other_joininfo = joininfo_member(new_relids,
joinrel->joininfo);
if (other_joininfo)
{
other_joininfo->jinfo_restrictinfo =
(List *) LispUnion(restrict_info,
other_joininfo->jinfo_restrictinfo);
}
else
{
JoinInfo *new_joininfo = makeNode(JoinInfo);
new_joininfo->otherrels = new_relids;
new_joininfo->jinfo_restrictinfo = restrict_info;
new_joininfo->mergejoinable = mergejoinable;
new_joininfo->hashjoinable = hashjoinable;
new_joininfo->inactive = false;
joinrel->joininfo = lappend(joinrel->joininfo,
new_joininfo);
}
}
}
}
}
}
foreach(xrel, outerrels)
{
rel = (RelOptInfo *) lfirst(xrel);
rel->superrels = NIL;
}
}
/*
* final_join_rels
* Find the join relation that includes all the original
* relations, i.e. the final join result.
*
* 'join_rel_list' is a list of join relations.
*
* Returns the list of final join relations.
*/
static List *
geqo_final_join_rels(List *join_rel_list)
{
List *xrel = NIL;
List *t_list = NIL;
/*
* find the relations that has no further joins, i.e., its joininfos
* all have otherrels nil.
*/
foreach(xrel, join_rel_list)
{
RelOptInfo *rel = (RelOptInfo *) lfirst(xrel);
List *xjoininfo = NIL;
bool final = true;
foreach(xjoininfo, rel->joininfo)
{
JoinInfo *joininfo = (JoinInfo *) lfirst(xjoininfo);
if (joininfo->otherrels != NIL)
{
final = false;
break;
}
}
if (final)
{
t_list = lappend(t_list, rel);
}
}
return t_list;
}
/*
* add_superrels
* add rel to the temporary property list superrels.
*
* 'rel' a rel node
* 'super_rel' rel node of a join relation that includes rel
*
* Modifies the superrels field of rel
*/
static void
add_superrels(RelOptInfo *rel, RelOptInfo *super_rel)
{
rel->superrels = lappend(rel->superrels, super_rel);
}
/*
* nonoverlap_rels
* test if two join relations overlap, i.e., includes the same
* relation.
*
* 'rel1' and 'rel2' are two join relations
*
* Returns non-nil if rel1 and rel2 do not overlap.
*/
static bool
nonoverlap_rels(RelOptInfo *rel1, RelOptInfo *rel2)
{
return nonoverlap_sets(rel1->relids, rel2->relids);
}
static bool
nonoverlap_sets(List *s1, List *s2)
{
List *x = NIL;
foreach(x, s1)
{
int e = lfirsti(x);
if (intMember(e, s2))
return false;
}
return true;
}
#endif /* NOTUSED */
/*
* geqo_joinrel_size
* compute estimate for join relation tuples, even for
* long join queries; so get logarithm of size when MAXINT overflow;
*/
static void
geqo_joinrel_size(RelOptInfo *joinrel, RelOptInfo *outer_rel, RelOptInfo *inner_rel)
{
Cost temp;
int ntuples;
temp = (Cost) inner_rel->tuples * (Cost) outer_rel->tuples; /* cartesian product */
if (joinrel->restrictinfo)
temp = temp * product_selec(joinrel->restrictinfo);
if (temp >= (MAXINT - 1))
ntuples = ceil(geqo_log((double) temp, (double) GEQO_LOG_BASE));
else
ntuples = ceil((double) temp);
if (ntuples < 1)
ntuples = 1; /* make the best case 1 instead of 0 */
joinrel->tuples = ntuples;
}
double
geqo_log(double x, double b)
{
return log(x) / log(b);
}
static RelOptInfo *
geqo_nth(int stop, List *rels)
{

View File

@@ -5,7 +5,7 @@
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: geqo_params.c,v 1.13 1999/02/13 23:16:10 momjian Exp $
* $Id: geqo_params.c,v 1.14 1999/02/15 03:22:01 momjian Exp $
*
*-------------------------------------------------------------------------
*/
@@ -61,6 +61,7 @@
static int gimme_pool_size(int string_length);
static int gimme_number_generations(int pool_size, int effort);
static int next_token(FILE *, char *, int);
static double geqo_log(double x, double b);
/*
* geqo_param
@@ -338,3 +339,9 @@ gimme_number_generations(int pool_size, int effort)
return effort * number_gens;
}
static double
geqo_log(double x, double b)
{
return (log(x) / log(b));
}

View File

@@ -1,104 +0,0 @@
/*-------------------------------------------------------------------------
*
* geqo_paths.c
* Routines to process redundant paths and relations
*
* Copyright (c) 1994, Regents of the University of California
*
* $Id: geqo_paths.c,v 1.21 1999/02/15 02:04:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "postgres.h"
#include "nodes/pg_list.h"
#include "nodes/relation.h"
#include "nodes/primnodes.h"
#include "utils/palloc.h"
#include "utils/elog.h"
#include "optimizer/internal.h"
#include "optimizer/paths.h"
#include "optimizer/pathnode.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/geqo_paths.h"
static List *geqo_prune_rel(RelOptInfo *rel, List *other_rels);
/*
* geqo_prune_rels
* Removes any redundant relation entries from a list of rel nodes
* 'rel_list'.
*
* Returns the resulting list.
*
*/
List *
geqo_prune_rels(List *rel_list)
{
List *temp_list = NIL;
if (rel_list != NIL)
{
temp_list = lcons(lfirst(rel_list),
geqo_prune_rels(geqo_prune_rel((RelOptInfo *) lfirst(rel_list),
lnext(rel_list))));
}
return temp_list;
}
/*
* geqo_prune_rel
* Prunes those relations from 'other_rels' that are redundant with
* 'rel'. A relation is redundant if it is built up of the same
* relations as 'rel'. Paths for the redundant relation are merged into
* the pathlist of 'rel'.
*
* Returns a list of non-redundant relations, and sets the pathlist field
* of 'rel' appropriately.
*
*/
static List *
geqo_prune_rel(RelOptInfo *rel, List *other_rels)
{
List *t_list = NIL;
List *i;
RelOptInfo *other_rel;
foreach(i, other_rels)
{
other_rel = (RelOptInfo *) lfirst(i);
if (same(rel->relids, other_rel->relids))
{
rel->pathlist = add_pathlist(rel,
rel->pathlist,
other_rel->pathlist);
}
else
{
t_list = lappend(t_list, other_rel);
}
}
return t_list;
}
/*
* geqo_set_cheapest
* For a relation 'rel' (which corresponds to a join
* relation), set pointers to the cheapest path
*/
void
geqo_set_cheapest(RelOptInfo *rel)
{
JoinPath *cheapest = (JoinPath *)set_cheapest(rel, rel->pathlist);
if (IsA_JoinPath(cheapest))
rel->size = compute_joinrel_size(cheapest);
else
rel->size = 0;
}