geqo_eval.c

来自「PostgreSQL7.4.6 for Linux」· C语言 代码 · 共 174 行

C
174
字号
/*------------------------------------------------------------------------ * * geqo_eval.c *	  Routines to evaluate query trees * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * $Header: /cvsroot/pgsql/src/backend/optimizer/geqo/geqo_eval.c,v 1.65 2003/08/04 02:39:59 momjian Exp $ * *------------------------------------------------------------------------- *//* contributed by:   =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=   *  Martin Utesch				 * Institute of Automatic Control	   *   =							 = University of Mining and Technology =   *  utesch@aut.tu-freiberg.de  * Freiberg, Germany				   *   =*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*= */#include "postgres.h"#include <float.h>#include <limits.h>#include <math.h>#include "optimizer/geqo.h"#include "optimizer/pathnode.h"#include "optimizer/paths.h"#include "utils/memutils.h"/* * geqo_eval * * Returns cost of a query tree as an individual of the population. */Costgeqo_eval(Query *root, List *initial_rels, Gene *tour, int num_gene){	MemoryContext mycontext;	MemoryContext oldcxt;	RelOptInfo *joinrel;	Cost		fitness;	List	   *savelist;	/*	 * Because gimme_tree considers both left- and right-sided trees,	 * there is no difference between a tour (a,b,c,d,...) and a tour	 * (b,a,c,d,...) --- the same join orders will be considered. To avoid	 * redundant cost calculations, we simply reject tours where tour[0] >	 * tour[1], assigning them an artificially bad fitness.	 *	 * (It would be better to tweak the GEQO logic to not generate such tours	 * in the first place, but I'm not sure of all the implications in the	 * mutation logic.)	 */	if (num_gene >= 2 && tour[0] > tour[1])		return DBL_MAX;	/*	 * Create a private memory context that will hold all temp storage	 * allocated inside gimme_tree().	 *	 * Since geqo_eval() will be called many times, we can't afford to let	 * all that memory go unreclaimed until end of statement.  Note we	 * make the temp context a child of the planner's normal context, so	 * that it will be freed even if we abort via ereport(ERROR).	 */	mycontext = AllocSetContextCreate(CurrentMemoryContext,									  "GEQO",									  ALLOCSET_DEFAULT_MINSIZE,									  ALLOCSET_DEFAULT_INITSIZE,									  ALLOCSET_DEFAULT_MAXSIZE);	oldcxt = MemoryContextSwitchTo(mycontext);	/*	 * preserve root->join_rel_list, which gimme_tree changes; without	 * this, it'll be pointing at recycled storage after the	 * MemoryContextDelete below.	 */	savelist = root->join_rel_list;	/* construct the best path for the given combination of relations */	joinrel = gimme_tree(root, initial_rels, tour, num_gene);	/*	 * compute fitness	 *	 * XXX geqo does not currently support optimization for partial result	 * retrieval --- how to fix?	 */	if (joinrel)		fitness = joinrel->cheapest_total_path->total_cost;	else		fitness = DBL_MAX;	/* restore join_rel_list */	root->join_rel_list = savelist;	/* release all the memory acquired within gimme_tree */	MemoryContextSwitchTo(oldcxt);	MemoryContextDelete(mycontext);	return fitness;}/* * gimme_tree *	  Form planner estimates for a join tree constructed in the specified *	  order. * *	 'root' is the Query *	 'initial_rels' is the list of initial relations (FROM-list items) *	 'tour' is the proposed join order, of length 'num_gene' * * 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. * * Note that at each step we consider using the next rel as both left and * right side of a join.  However, we cannot build general ("bushy") plan * trees this way, only left-sided and right-sided trees. */RelOptInfo *gimme_tree(Query *root, List *initial_rels,		   Gene *tour, int num_gene){	RelOptInfo *joinrel;	int			cur_rel_index;	int			rel_count;	/*	 * Start with the first relation ...	 */	cur_rel_index = (int) tour[0];	joinrel = (RelOptInfo *) nth(cur_rel_index - 1, initial_rels);	/*	 * And add on each relation in the specified order ...	 */	for (rel_count = 1; rel_count < num_gene; rel_count++)	{		RelOptInfo *inner_rel;		RelOptInfo *new_rel;		cur_rel_index = (int) tour[rel_count];		inner_rel = (RelOptInfo *) nth(cur_rel_index - 1, initial_rels);		/*		 * Construct a RelOptInfo representing the previous joinrel joined		 * to inner_rel.  These are always inner joins.  Note that we		 * expect the joinrel not to exist in root->join_rel_list yet, and		 * so the paths constructed for it will only include the ones we		 * want.		 */		new_rel = make_join_rel(root, joinrel, inner_rel, JOIN_INNER);		/* Fail if join order is not valid */		if (new_rel == NULL)			return NULL;		/* Find and save the cheapest paths for this rel */		set_cheapest(new_rel);		/* and repeat... */		joinrel = new_rel;	}	return joinrel;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?