Commit 8a30cc21 authored by Tom Lane's avatar Tom Lane

Make the planner estimate costs for nestloop inner indexscans on the basis

that the Mackert-Lohmann formula applies across all the repetitions of the
nestloop, not just each scan independently.  We use the M-L formula to
estimate the number of pages fetched from the index as well as from the table;
that isn't what it was designed for, but it seems reasonably applicable
anyway.  This makes large numbers of repetitions look much cheaper than
before, which accords with many reports we've received of overestimation
of the cost of a nestloop.  Also, change the index access cost model to
charge random_page_cost per index leaf page touched, while explicitly
not counting anything for access to metapage or upper tree pages.  This
may all need tweaking after we get some field experience, but in simple
tests it seems to be giving saner results than before.  The main thing
is to get the infrastructure in place to let cost_index() and amcostestimate
functions take repeated scans into account at all.  Per my recent proposal.

Note: this patch changes pg_proc.h, but I did not force initdb because
the changes are basically cosmetic --- the system does not look into
pg_proc to decide how to call an index amcostestimate function, and
there's no way to call such a function from SQL at all.
parent 05631354
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.13 2006/06/05 02:49:58 tgl Exp $ -->
<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.14 2006/06/06 17:59:57 tgl Exp $ -->
<chapter id="indexam">
<title>Index Access Method Interface Definition</title>
......@@ -344,6 +344,7 @@ void
amcostestimate (PlannerInfo *root,
IndexOptInfo *index,
List *indexQuals,
RelOptInfo *outer_rel,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
......@@ -681,6 +682,7 @@ void
amcostestimate (PlannerInfo *root,
IndexOptInfo *index,
List *indexQuals,
RelOptInfo *outer_rel,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity,
......@@ -718,6 +720,20 @@ amcostestimate (PlannerInfo *root,
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>outer_rel</term>
<listitem>
<para>
If the index is being considered for use in a join inner indexscan,
the planner's information about the outer side of the join. Otherwise
NULL. When non-NULL, some of the qual clauses will be join clauses
with this rel rather than being simple restriction clauses. Also,
the cost estimator should expect that the index scan will be repeated
for each row of the outer rel.
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
......@@ -808,6 +824,11 @@ amcostestimate (PlannerInfo *root,
table.
</para>
<para>
In the join case, the returned numbers should be averages expected for
any one scan of the index.
</para>
<procedure>
<title>Cost Estimation</title>
<para>
......@@ -859,6 +880,9 @@ amcostestimate (PlannerInfo *root,
*indexTotalCost = seq_page_cost * numIndexPages +
(cpu_index_tuple_cost + index_qual_cost.per_tuple) * numIndexTuples;
</programlisting>
However, the above does not account for amortization of index reads
across repeated index scans in the join case.
</para>
</step>
......
This diff is collapsed.
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.103 2006/03/05 15:58:28 momjian Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/joinpath.c,v 1.104 2006/06/06 17:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -36,7 +36,7 @@ static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
RelOptInfo *outerrel, RelOptInfo *innerrel,
List *restrictlist, JoinType jointype);
static Path *best_appendrel_indexscan(PlannerInfo *root, RelOptInfo *rel,
Relids outer_relids, JoinType jointype);
RelOptInfo *outer_rel, JoinType jointype);
static List *select_mergejoin_clauses(RelOptInfo *joinrel,
RelOptInfo *outerrel,
RelOptInfo *innerrel,
......@@ -401,12 +401,10 @@ match_unsorted_outer(PlannerInfo *root,
{
if (IsA(inner_cheapest_total, AppendPath))
bestinnerjoin = best_appendrel_indexscan(root, innerrel,
outerrel->relids,
jointype);
outerrel, jointype);
else if (innerrel->rtekind == RTE_RELATION)
bestinnerjoin = best_inner_indexscan(root, innerrel,
outerrel->relids,
jointype);
outerrel, jointype);
}
}
......@@ -791,13 +789,13 @@ hash_inner_and_outer(PlannerInfo *root,
/*
* best_appendrel_indexscan
* Finds the best available set of inner indexscans for a nestloop join
* with the given append relation on the inside and the given outer_relids
* with the given append relation on the inside and the given outer_rel
* outside. Returns an AppendPath comprising the best inner scans, or
* NULL if there are no possible inner indexscans.
*/
static Path *
best_appendrel_indexscan(PlannerInfo *root, RelOptInfo *rel,
Relids outer_relids, JoinType jointype)
RelOptInfo *outer_rel, JoinType jointype)
{
int parentRTindex = rel->relid;
List *append_paths = NIL;
......@@ -832,7 +830,7 @@ best_appendrel_indexscan(PlannerInfo *root, RelOptInfo *rel,
* Get the best innerjoin indexpath (if any) for this child rel.
*/
bestinnerjoin = best_inner_indexscan(root, childrel,
outer_relids, jointype);
outer_rel, jointype);
/*
* If no luck on an indexpath for this rel, we'll still consider
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.78 2006/03/05 15:58:28 momjian Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/path/orindxpath.c,v 1.79 2006/06/06 17:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -107,7 +107,7 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
* Use the generate_bitmap_or_paths() machinery to estimate the
* value of each OR clause. We can use regular restriction
* clauses along with the OR clause contents to generate
* indexquals. We pass outer_relids = NULL so that sub-clauses
* indexquals. We pass outer_rel = NULL so that sub-clauses
* that are actually joins will be ignored.
*/
List *orpaths;
......@@ -116,7 +116,7 @@ create_or_index_quals(PlannerInfo *root, RelOptInfo *rel)
orpaths = generate_bitmap_or_paths(root, rel,
list_make1(rinfo),
rel->baserestrictinfo,
false, NULL);
NULL);
/* Locate the cheapest OR path */
foreach(k, orpaths)
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.14 2006/04/28 20:57:49 tgl Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/plan/planagg.c,v 1.15 2006/06/06 17:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -373,7 +373,7 @@ build_minmax_path(PlannerInfo *root, RelOptInfo *rel, MinMaxAggInfo *info)
restrictclauses,
NIL,
indexscandir,
false);
NULL);
/*
* Estimate actual cost of fetching just one row.
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.127 2006/03/05 15:58:31 momjian Exp $
* $PostgreSQL: pgsql/src/backend/optimizer/util/pathnode.c,v 1.128 2006/06/06 17:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -420,8 +420,8 @@ create_seqscan_path(PlannerInfo *root, RelOptInfo *rel)
* 'indexscandir' is ForwardScanDirection or BackwardScanDirection
* for an ordered index, or NoMovementScanDirection for
* an unordered index.
* 'isjoininner' is TRUE if this is a join inner indexscan path.
* (pathkeys and indexscandir are ignored if so.)
* 'outer_rel' is the outer relation if this is a join inner indexscan path.
* (pathkeys and indexscandir are ignored if so.) NULL if not.
*
* Returns the new path node.
*/
......@@ -431,7 +431,7 @@ create_index_path(PlannerInfo *root,
List *clause_groups,
List *pathkeys,
ScanDirection indexscandir,
bool isjoininner)
RelOptInfo *outer_rel)
{
IndexPath *pathnode = makeNode(IndexPath);
RelOptInfo *rel = index->rel;
......@@ -445,7 +445,7 @@ create_index_path(PlannerInfo *root,
* don't really care what order it's scanned in. (We could expect the
* caller to supply the correct values, but it's easier to force it here.)
*/
if (isjoininner)
if (outer_rel != NULL)
{
pathkeys = NIL;
indexscandir = NoMovementScanDirection;
......@@ -466,10 +466,10 @@ create_index_path(PlannerInfo *root,
pathnode->indexclauses = allclauses;
pathnode->indexquals = indexquals;
pathnode->isjoininner = isjoininner;
pathnode->isjoininner = (outer_rel != NULL);
pathnode->indexscandir = indexscandir;
if (isjoininner)
if (outer_rel != NULL)
{
/*
* We must compute the estimated number of output rows for the
......@@ -505,7 +505,7 @@ create_index_path(PlannerInfo *root,
pathnode->rows = rel->rows;
}
cost_index(pathnode, root, index, indexquals, isjoininner);
cost_index(pathnode, root, index, indexquals, outer_rel);
return pathnode;
}
......@@ -515,6 +515,9 @@ create_index_path(PlannerInfo *root,
* Creates a path node for a bitmap scan.
*
* 'bitmapqual' is a tree of IndexPath, BitmapAndPath, and BitmapOrPath nodes.
*
* If this is a join inner indexscan path, the component IndexPaths should
* have been costed accordingly, and TRUE should be passed for isjoininner.
*/
BitmapHeapPath *
create_bitmap_heap_path(PlannerInfo *root,
......@@ -560,7 +563,7 @@ create_bitmap_heap_path(PlannerInfo *root,
pathnode->rows = rel->rows;
}
cost_bitmap_heap_scan(&pathnode->path, root, rel, bitmapqual, false);
cost_bitmap_heap_scan(&pathnode->path, root, rel, bitmapqual);
return pathnode;
}
......
......@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.206 2006/06/05 02:49:58 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.207 2006/06/06 17:59:57 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -4465,6 +4465,7 @@ string_to_bytea_const(const char *str, size_t str_len)
static void
genericcostestimate(PlannerInfo *root,
IndexOptInfo *index, List *indexQuals,
RelOptInfo *outer_rel,
double numIndexTuples,
Cost *indexStartupCost,
Cost *indexTotalCost,
......@@ -4538,26 +4539,61 @@ genericcostestimate(PlannerInfo *root,
/*
* Estimate the number of index pages that will be retrieved.
*
* For all currently-supported index types, the first page of the index is
* a metadata page, and we should figure on fetching that plus a pro-rated
* fraction of the remaining pages.
* We use the simplistic method of taking a pro-rata fraction of the
* total number of index pages. In effect, this counts only leaf pages
* and not any overhead such as index metapage or upper tree levels.
* In practice this seems a better approximation than charging for
* access to the upper levels, perhaps because those tend to stay in
* cache under load.
*/
if (index->pages > 1 && index->tuples > 0)
{
numIndexPages = (numIndexTuples / index->tuples) * (index->pages - 1);
numIndexPages += 1; /* count the metapage too */
numIndexPages = ceil(numIndexPages);
}
if (index->pages > 1 && index->tuples > 1)
numIndexPages = ceil(numIndexTuples * index->pages / index->tuples);
else
numIndexPages = 1.0;
/*
* Compute the index access cost.
* Now compute the disk access costs.
*
* Disk cost: our generic assumption is that the index pages will be read
* sequentially, so they cost seq_page_cost each, not random_page_cost.
* The above calculations are all per-index-scan. However, if we are
* in a nestloop inner scan, we can expect the scan to be repeated (with
* different search keys) for each row of the outer relation. This
* creates the potential for cache effects to reduce the number of
* disk page fetches needed. We want to estimate the average per-scan
* I/O cost in the presence of caching.
*
* We use the Mackert-Lohman formula (see costsize.c for details) to
* estimate the total number of page fetches that occur. While this
* wasn't what it was designed for, it seems a reasonable model anyway.
* Note that we are counting pages not tuples anymore, so we take
* N = T = index size, as if there were one "tuple" per page.
*/
*indexTotalCost = seq_page_cost * numIndexPages;
if (outer_rel != NULL && outer_rel->rows > 1)
{
double num_scans = outer_rel->rows;
double pages_fetched;
/* total page fetches ignoring cache effects */
pages_fetched = numIndexPages * num_scans;
/* use Mackert and Lohman formula to adjust for cache effects */
pages_fetched = index_pages_fetched(pages_fetched,
index->pages,
index->rel->pages);
/*
* Now compute the total disk access cost, and then report a
* pro-rated share for one index scan.
*/
*indexTotalCost = (pages_fetched * random_page_cost) / num_scans;
}
else
{
/*
* For a single index scan, we just charge random_page_cost per page
* touched.
*/
*indexTotalCost = numIndexPages * random_page_cost;
}
/*
* CPU cost: any complex expressions in the indexquals will need to be
......@@ -4594,10 +4630,11 @@ btcostestimate(PG_FUNCTION_ARGS)
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
List *indexQuals = (List *) PG_GETARG_POINTER(2);
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(3);
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
double *indexCorrelation = (double *) PG_GETARG_POINTER(7);
Oid relid;
AttrNumber colnum;
HeapTuple tuple;
......@@ -4728,7 +4765,7 @@ btcostestimate(PG_FUNCTION_ARGS)
numIndexTuples = btreeSelectivity * index->rel->tuples;
}
genericcostestimate(root, index, indexQuals, numIndexTuples,
genericcostestimate(root, index, indexQuals, outer_rel, numIndexTuples,
indexStartupCost, indexTotalCost,
indexSelectivity, indexCorrelation);
......@@ -4800,12 +4837,13 @@ hashcostestimate(PG_FUNCTION_ARGS)
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
List *indexQuals = (List *) PG_GETARG_POINTER(2);
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(3);
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
double *indexCorrelation = (double *) PG_GETARG_POINTER(7);
genericcostestimate(root, index, indexQuals, 0.0,
genericcostestimate(root, index, indexQuals, outer_rel, 0.0,
indexStartupCost, indexTotalCost,
indexSelectivity, indexCorrelation);
......@@ -4818,12 +4856,13 @@ gistcostestimate(PG_FUNCTION_ARGS)
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
List *indexQuals = (List *) PG_GETARG_POINTER(2);
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(3);
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
double *indexCorrelation = (double *) PG_GETARG_POINTER(7);
genericcostestimate(root, index, indexQuals, 0.0,
genericcostestimate(root, index, indexQuals, outer_rel, 0.0,
indexStartupCost, indexTotalCost,
indexSelectivity, indexCorrelation);
......@@ -4836,12 +4875,13 @@ gincostestimate(PG_FUNCTION_ARGS)
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
IndexOptInfo *index = (IndexOptInfo *) PG_GETARG_POINTER(1);
List *indexQuals = (List *) PG_GETARG_POINTER(2);
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(3);
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(4);
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(5);
double *indexCorrelation = (double *) PG_GETARG_POINTER(6);
RelOptInfo *outer_rel = (RelOptInfo *) PG_GETARG_POINTER(3);
Cost *indexStartupCost = (Cost *) PG_GETARG_POINTER(4);
Cost *indexTotalCost = (Cost *) PG_GETARG_POINTER(5);
Selectivity *indexSelectivity = (Selectivity *) PG_GETARG_POINTER(6);
double *indexCorrelation = (double *) PG_GETARG_POINTER(7);
genericcostestimate(root, index, indexQuals, 0.0,
genericcostestimate(root, index, indexQuals, outer_rel, 0.0,
indexStartupCost, indexTotalCost,
indexSelectivity, indexCorrelation);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.412 2006/05/19 19:08:26 alvherre Exp $
* $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.413 2006/06/06 17:59:57 tgl Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
......@@ -678,7 +678,7 @@ DATA(insert OID = 332 ( btbulkdelete PGNSP PGUID 12 f f t f v 4 2281 "2281 2
DESCR("btree(internal)");
DATA(insert OID = 972 ( btvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281 2281" _null_ _null_ _null_ btvacuumcleanup - _null_ ));
DESCR("btree(internal)");
DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ btcostestimate - _null_ ));
DATA(insert OID = 1268 ( btcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ btcostestimate - _null_ ));
DESCR("btree(internal)");
DATA(insert OID = 339 ( poly_same PGNSP PGUID 12 f f t f i 2 16 "604 604" _null_ _null_ _null_ poly_same - _null_ ));
......@@ -795,7 +795,7 @@ DATA(insert OID = 442 ( hashbulkdelete PGNSP PGUID 12 f f t f v 4 2281 "2281
DESCR("hash(internal)");
DATA(insert OID = 425 ( hashvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281 2281" _null_ _null_ _null_ hashvacuumcleanup - _null_ ));
DESCR("hash(internal)");
DATA(insert OID = 438 ( hashcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ hashcostestimate - _null_ ));
DATA(insert OID = 438 ( hashcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ hashcostestimate - _null_ ));
DESCR("hash(internal)");
DATA(insert OID = 449 ( hashint2 PGNSP PGUID 12 f f t f i 1 23 "21" _null_ _null_ _null_ hashint2 - _null_ ));
......@@ -1061,7 +1061,7 @@ DATA(insert OID = 776 ( gistbulkdelete PGNSP PGUID 12 f f t f v 4 2281 "2281
DESCR("gist(internal)");
DATA(insert OID = 2561 ( gistvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281 2281" _null_ _null_ _null_ gistvacuumcleanup - _null_ ));
DESCR("gist(internal)");
DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gistcostestimate - _null_ ));
DATA(insert OID = 772 ( gistcostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gistcostestimate - _null_ ));
DESCR("gist(internal)");
DATA(insert OID = 784 ( tintervaleq PGNSP PGUID 12 f f t f i 2 16 "704 704" _null_ _null_ _null_ tintervaleq - _null_ ));
......@@ -3847,7 +3847,7 @@ DATA(insert OID = 2739 ( ginbulkdelete PGNSP PGUID 12 f f t f v 4 2281 "2281
DESCR("gin(internal)");
DATA(insert OID = 2740 ( ginvacuumcleanup PGNSP PGUID 12 f f t f v 2 2281 "2281 2281" _null_ _null_ _null_ ginvacuumcleanup - _null_ ));
DESCR("gin(internal)");
DATA(insert OID = 2741 ( gincostestimate PGNSP PGUID 12 f f t f v 7 2278 "2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gincostestimate - _null_ ));
DATA(insert OID = 2741 ( gincostestimate PGNSP PGUID 12 f f t f v 8 2278 "2281 2281 2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gincostestimate - _null_ ));
DESCR("gin(internal)");
/* GIN array support */
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.124 2006/03/05 15:58:57 momjian Exp $
* $PostgreSQL: pgsql/src/include/nodes/relation.h,v 1.125 2006/06/06 17:59:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -407,6 +407,9 @@ typedef struct Path
*
* 'isjoininner' is TRUE if the path is a nestloop inner scan (that is,
* some of the index conditions are join rather than restriction clauses).
* Note that the path costs will be calculated differently from a plain
* indexscan in this case, and in addition there's a special 'rows' value
* different from the parent RelOptInfo's (see below).
*
* 'indexscandir' is one of:
* ForwardScanDirection: forward scan of an ordered index
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.75 2006/06/05 03:03:42 tgl Exp $
* $PostgreSQL: pgsql/src/include/optimizer/cost.h,v 1.76 2006/06/06 17:59:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -41,7 +41,7 @@ extern DLLIMPORT double random_page_cost;
extern DLLIMPORT double cpu_tuple_cost;
extern DLLIMPORT double cpu_index_tuple_cost;
extern DLLIMPORT double cpu_operator_cost;
extern double effective_cache_size;
extern DLLIMPORT double effective_cache_size;
extern Cost disable_cost;
extern bool enable_seqscan;
extern bool enable_indexscan;
......@@ -55,11 +55,13 @@ extern bool enable_hashjoin;
extern bool constraint_exclusion;
extern double clamp_row_est(double nrows);
extern double index_pages_fetched(double tuples_fetched, BlockNumber pages,
BlockNumber other_pages);
extern void cost_seqscan(Path *path, PlannerInfo *root, RelOptInfo *baserel);
extern void cost_index(IndexPath *path, PlannerInfo *root, IndexOptInfo *index,
List *indexQuals, bool is_injoin);
List *indexQuals, RelOptInfo *outer_rel);
extern void cost_bitmap_heap_scan(Path *path, PlannerInfo *root, RelOptInfo *baserel,
Path *bitmapqual, bool is_injoin);
Path *bitmapqual);
extern void cost_bitmap_and_node(BitmapAndPath *path, PlannerInfo *root);
extern void cost_bitmap_or_node(BitmapOrPath *path, PlannerInfo *root);
extern void cost_bitmap_tree_node(Path *path, Cost *cost, Selectivity *selec);
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.67 2006/03/05 15:58:57 momjian Exp $
* $PostgreSQL: pgsql/src/include/optimizer/pathnode.h,v 1.68 2006/06/06 17:59:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -33,7 +33,7 @@ extern IndexPath *create_index_path(PlannerInfo *root,
List *clause_groups,
List *pathkeys,
ScanDirection indexscandir,
bool isjoininner);
RelOptInfo *outer_rel);
extern BitmapHeapPath *create_bitmap_heap_path(PlannerInfo *root,
RelOptInfo *rel,
Path *bitmapqual,
......
......@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.92 2006/03/05 15:58:57 momjian Exp $
* $PostgreSQL: pgsql/src/include/optimizer/paths.h,v 1.93 2006/06/06 17:59:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -44,10 +44,9 @@ typedef enum
extern void create_index_paths(PlannerInfo *root, RelOptInfo *rel);
extern List *generate_bitmap_or_paths(PlannerInfo *root, RelOptInfo *rel,
List *clauses, List *outer_clauses,
bool isjoininner,
Relids outer_relids);
RelOptInfo *outer_rel);
extern Path *best_inner_indexscan(PlannerInfo *root, RelOptInfo *rel,
Relids outer_relids, JoinType jointype);
RelOptInfo *outer_rel, JoinType jointype);
extern List *group_clauses_by_indexkey(IndexOptInfo *index,
List *clauses, List *outer_clauses,
Relids outer_relids,
......
......@@ -6,7 +6,7 @@
* for developers. If you edit any of these, be sure to do a *full*
* rebuild (and an initdb if noted).
*
* $PostgreSQL: pgsql/src/include/pg_config_manual.h,v 1.21 2006/04/03 23:35:05 tgl Exp $
* $PostgreSQL: pgsql/src/include/pg_config_manual.h,v 1.22 2006/06/06 17:59:58 tgl Exp $
*------------------------------------------------------------------------
*/
......@@ -65,7 +65,7 @@
/*
* Maximum number of arguments to a function.
*
* The minimum value is 8 (index creation uses 8-argument functions).
* The minimum value is 8 (index cost estimation uses 8-argument functions).
* The maximum possible value is around 600 (limited by index tuple size in
* pg_proc's index; BLCKSZ larger than 8K would allow more). Values larger
* than needed will waste memory and processing time, but do not directly
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment