costsize.c

来自「PostgreSQL 8.1.4的源码 适用于Linux下的开源数据库系统」· C语言 代码 · 共 2,000 行 · 第 1/5 页

C
2,000
字号
		cost_qual_eval(&index_qual_cost, indexQuals);		/* any startup cost still has to be paid ... */		cpu_per_tuple -= index_qual_cost.per_tuple;	}	run_cost += cpu_per_tuple * tuples_fetched;	path->path.startup_cost = startup_cost;	path->path.total_cost = startup_cost + run_cost;}/* * cost_bitmap_heap_scan *	  Determines and returns the cost of scanning a relation using a bitmap *	  index-then-heap plan. * * 'baserel' is the relation to be scanned * 'bitmapqual' is a tree of IndexPaths, BitmapAndPaths, and BitmapOrPaths * 'is_injoin' is T if we are considering using the scan as the inside *		of a nestloop join (hence, some of the quals are join clauses) */voidcost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,					  Path *bitmapqual, bool is_injoin){	Cost		startup_cost = 0;	Cost		run_cost = 0;	Cost		indexTotalCost;	Selectivity indexSelectivity;	Cost		cpu_per_tuple;	Cost		cost_per_page;	double		tuples_fetched;	double		pages_fetched;	double		T;	/* Should only be applied to base relations */	Assert(IsA(baserel, RelOptInfo));	Assert(baserel->relid > 0);	Assert(baserel->rtekind == RTE_RELATION);	if (!enable_bitmapscan)		startup_cost += disable_cost;	/*	 * Fetch total cost of obtaining the bitmap, as well as its total	 * selectivity.	 */	cost_bitmap_tree_node(bitmapqual, &indexTotalCost, &indexSelectivity);	startup_cost += indexTotalCost;	/*	 * The number of heap pages that need to be fetched is the same as the	 * Mackert and Lohman formula for the case T <= b (ie, no re-reads	 * needed).	 */	tuples_fetched = clamp_row_est(indexSelectivity * baserel->tuples);	T = (baserel->pages > 1) ? (double) baserel->pages : 1.0;	pages_fetched = (2.0 * T * tuples_fetched) / (2.0 * T + tuples_fetched);	if (pages_fetched > T)		pages_fetched = T;	/*	 * For small numbers of pages we should charge random_page_cost apiece,	 * while if nearly all the table's pages are being read, it's more	 * appropriate to charge 1.0 apiece.  The effect is nonlinear, too. For	 * lack of a better idea, interpolate like this to determine the cost per	 * page.	 */	if (pages_fetched >= 2.0)		cost_per_page = random_page_cost -			(random_page_cost - 1.0) * sqrt(pages_fetched / T);	else		cost_per_page = random_page_cost;	run_cost += pages_fetched * cost_per_page;	/*	 * Estimate CPU costs per tuple.	 *	 * Often the indexquals don't need to be rechecked at each tuple ... but	 * not always, especially not if there are enough tuples involved that the	 * bitmaps become lossy.  For the moment, just assume they will be	 * rechecked always.	 */	startup_cost += baserel->baserestrictcost.startup;	cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost.per_tuple;	run_cost += cpu_per_tuple * tuples_fetched;	path->startup_cost = startup_cost;	path->total_cost = startup_cost + run_cost;}/* * cost_bitmap_tree_node *		Extract cost and selectivity from a bitmap tree node (index/and/or) */voidcost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec){	if (IsA(path, IndexPath))	{		*cost = ((IndexPath *) path)->indextotalcost;		*selec = ((IndexPath *) path)->indexselectivity;	}	else if (IsA(path, BitmapAndPath))	{		*cost = path->total_cost;		*selec = ((BitmapAndPath *) path)->bitmapselectivity;	}	else if (IsA(path, BitmapOrPath))	{		*cost = path->total_cost;		*selec = ((BitmapOrPath *) path)->bitmapselectivity;	}	else		elog(ERROR, "unrecognized node type: %d", nodeTag(path));}/* * cost_bitmap_and_node *		Estimate the cost of a BitmapAnd node * * Note that this considers only the costs of index scanning and bitmap * creation, not the eventual heap access.	In that sense the object isn't * truly a Path, but it has enough path-like properties (costs in particular) * to warrant treating it as one. */voidcost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root){	Cost		totalCost;	Selectivity selec;	ListCell   *l;	/*	 * We estimate AND selectivity on the assumption that the inputs are	 * independent.  This is probably often wrong, but we don't have the info	 * to do better.	 *	 * The runtime cost of the BitmapAnd itself is estimated at 100x	 * cpu_operator_cost for each tbm_intersect needed.  Probably too small,	 * definitely too simplistic?	 */	totalCost = 0.0;	selec = 1.0;	foreach(l, path->bitmapquals)	{		Path	   *subpath = (Path *) lfirst(l);		Cost		subCost;		Selectivity subselec;		cost_bitmap_tree_node(subpath, &subCost, &subselec);		selec *= subselec;		totalCost += subCost;		if (l != list_head(path->bitmapquals))			totalCost += 100.0 * cpu_operator_cost;	}	path->bitmapselectivity = selec;	path->path.startup_cost = totalCost;	path->path.total_cost = totalCost;}/* * cost_bitmap_or_node *		Estimate the cost of a BitmapOr node * * See comments for cost_bitmap_and_node. */voidcost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root){	Cost		totalCost;	Selectivity selec;	ListCell   *l;	/*	 * We estimate OR selectivity on the assumption that the inputs are	 * non-overlapping, since that's often the case in "x IN (list)" type	 * situations.	Of course, we clamp to 1.0 at the end.	 *	 * The runtime cost of the BitmapOr itself is estimated at 100x	 * cpu_operator_cost for each tbm_union needed.  Probably too small,	 * definitely too simplistic?  We are aware that the tbm_unions are	 * optimized out when the inputs are BitmapIndexScans.	 */	totalCost = 0.0;	selec = 0.0;	foreach(l, path->bitmapquals)	{		Path	   *subpath = (Path *) lfirst(l);		Cost		subCost;		Selectivity subselec;		cost_bitmap_tree_node(subpath, &subCost, &subselec);		selec += subselec;		totalCost += subCost;		if (l != list_head(path->bitmapquals) &&			!IsA(subpath, IndexPath))			totalCost += 100.0 * cpu_operator_cost;	}	path->bitmapselectivity = Min(selec, 1.0);	path->path.startup_cost = totalCost;	path->path.total_cost = totalCost;}/* * cost_tidscan *	  Determines and returns the cost of scanning a relation using TIDs. */voidcost_tidscan(Path *path, PlannerInfo *root,			 RelOptInfo *baserel, List *tideval){	Cost		startup_cost = 0;	Cost		run_cost = 0;	Cost		cpu_per_tuple;	int			ntuples = list_length(tideval);	/* Should only be applied to base relations */	Assert(baserel->relid > 0);	Assert(baserel->rtekind == RTE_RELATION);	if (!enable_tidscan)		startup_cost += disable_cost;	/* disk costs --- assume each tuple on a different page */	run_cost += random_page_cost * ntuples;	/* CPU costs */	startup_cost += baserel->baserestrictcost.startup;	cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost.per_tuple;	run_cost += cpu_per_tuple * ntuples;	path->startup_cost = startup_cost;	path->total_cost = startup_cost + run_cost;}/* * cost_subqueryscan *	  Determines and returns the cost of scanning a subquery RTE. */voidcost_subqueryscan(Path *path, RelOptInfo *baserel){	Cost		startup_cost;	Cost		run_cost;	Cost		cpu_per_tuple;	/* Should only be applied to base relations that are subqueries */	Assert(baserel->relid > 0);	Assert(baserel->rtekind == RTE_SUBQUERY);	/*	 * Cost of path is cost of evaluating the subplan, plus cost of evaluating	 * any restriction clauses that will be attached to the SubqueryScan node,	 * plus cpu_tuple_cost to account for selection and projection overhead.	 */	path->startup_cost = baserel->subplan->startup_cost;	path->total_cost = baserel->subplan->total_cost;	startup_cost = baserel->baserestrictcost.startup;	cpu_per_tuple = cpu_tuple_cost + baserel->baserestrictcost.per_tuple;	run_cost = cpu_per_tuple * baserel->tuples;	path->startup_cost += startup_cost;	path->total_cost += startup_cost + run_cost;}/* * cost_functionscan *	  Determines and returns the cost of scanning a function RTE. */voidcost_functionscan(Path *path, PlannerInfo *root, RelOptInfo *baserel){	Cost		startup_cost = 0;	Cost		run_cost = 0;	Cost		cpu_per_tuple;	/* Should only be applied to base relations that are functions */	Assert(baserel->relid > 0);	Assert(baserel->rtekind == RTE_FUNCTION);	/*	 * For now, estimate function's cost at one operator eval per function	 * call.  Someday we should revive the function cost estimate columns in	 * pg_proc...	 */	cpu_per_tuple = cpu_operator_cost;	/* Add scanning CPU costs */	startup_cost += baserel->baserestrictcost.startup;	cpu_per_tuple += cpu_tuple_cost + baserel->baserestrictcost.per_tuple;	run_cost += cpu_per_tuple * baserel->tuples;	path->startup_cost = startup_cost;	path->total_cost = startup_cost + run_cost;}/* * cost_sort *	  Determines and returns the cost of sorting a relation, including *	  the cost of reading the input data. * * If the total volume of data to sort is less than work_mem, we will do * an in-memory sort, which requires no I/O and about t*log2(t) tuple * comparisons for t tuples. * * If the total volume exceeds work_mem, we switch to a tape-style merge * algorithm.  There will still be about t*log2(t) tuple comparisons in * total, but we will also need to write and read each tuple once per * merge pass.	We expect about ceil(log6(r)) merge passes where r is the * number of initial runs formed (log6 because tuplesort.c uses six-tape * merging).  Since the average initial run should be about twice work_mem, * we have *		disk traffic = 2 * relsize * ceil(log6(p / (2*work_mem))) *		cpu = comparison_cost * t * log2(t) * * The disk traffic is assumed to be half sequential and half random * accesses (XXX can't we refine that guess?) * * We charge two operator evals per tuple comparison, which should be in * the right ballpark in most cases. * * 'pathkeys' is a list of sort keys * 'input_cost' is the total cost for reading the input data * 'tuples' is the number of tuples in the relation * 'width' is the average tuple width in bytes * * NOTE: some callers currently pass NIL for pathkeys because they * can't conveniently supply the sort keys.  Since this routine doesn't * currently do anything with pathkeys anyway, that doesn't matter... * but if it ever does, it should react gracefully to lack of key data. * (Actually, the thing we'd most likely be interested in is just the number * of sort keys, which all callers *could* supply.) */voidcost_sort(Path *path, PlannerInfo *root,		  List *pathkeys, Cost input_cost, double tuples, int width){	Cost		startup_cost = input_cost;	Cost		run_cost = 0;	double		nbytes = relation_byte_size(tuples, width);	long		work_mem_bytes = work_mem * 1024L;	if (!enable_sort)		startup_cost += disable_cost;	/*	 * We want to be sure the cost of a sort is never estimated as zero, even	 * if passed-in tuple count is zero.  Besides, mustn't do log(0)...	 */	if (tuples < 2.0)		tuples = 2.0;	/*	 * CPU costs	 *	 * Assume about two operator evals per tuple comparison and N log2 N	 * comparisons	 */	startup_cost += 2.0 * cpu_operator_cost * tuples * LOG2(tuples);	/* disk costs */	if (nbytes > work_mem_bytes)	{		double		npages = ceil(nbytes / BLCKSZ);		double		nruns = (nbytes / work_mem_bytes) * 0.5;		double		log_runs = ceil(LOG6(nruns));		double		npageaccesses;		if (log_runs < 1.0)			log_runs = 1.0;		npageaccesses = 2.0 * npages * log_runs;		/* Assume half are sequential (cost 1), half are not */		startup_cost += npageaccesses *			(1.0 + cost_nonsequential_access(npages)) * 0.5;	}	/*	 * Also charge a small amount (arbitrarily set equal to operator cost) per	 * extracted tuple.	 */	run_cost += cpu_operator_cost * tuples;	path->startup_cost = startup_cost;	path->total_cost = startup_cost + run_cost;}/* * cost_material *	  Determines and returns the cost of materializing a relation, including

⌨️ 快捷键说明

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