diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index cc28888efe..d0edf22daa 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ .\" This is -*-nroff-*- .\" XXX standard disclaimer belongs here.... -.\" $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.2 2000/01/11 01:40:04 tgl Exp $ +.\" $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.3 2000/01/22 23:50:08 tgl Exp $ .TH "SYSTEM CATALOGS" INTRO 03/13/94 PostgreSQL PostgreSQL .SH "Section 7 - System Catalogs" .de LS @@ -138,6 +138,8 @@ pg_am regproc ambuild /* "build new index" function */ regproc amcreate /* - deprecated */ regproc amdestroy /* - deprecated */ + regproc amcostestimate /* estimate cost of an indexscan */ + .fi .nf M pg_amop @@ -148,10 +150,6 @@ pg_amop oid amopopr /* the operator */ int2 amopstrategy /* traversal/search strategy number to which this operator applies */ - regproc amopselect /* function to calculate the operator - selectivity */ - regproc amopnpages /* function to calculate the number of - pages that will be examined */ .fi .nf M pg_amproc diff --git a/doc/src/sgml/xindex.sgml b/doc/src/sgml/xindex.sgml index 771c30e485..e4d36e1cc5 100644 --- a/doc/src/sgml/xindex.sgml +++ b/doc/src/sgml/xindex.sgml @@ -1,5 +1,5 @@ @@ -403,20 +403,9 @@ CREATE OPERATOR = ( the oids of the operators for the opclass (which we'll get in just a minute) - - amopselect, amopnpages - cost functions - - - The cost functions are used by the query optimizer to decide whether or - not to use a given index in a scan. Fortunately, these already exist. - The two functions we'll use are btreesel, which - estimates the selectivity of the B-tree, and - btreenpage, which estimates the number of pages a - search will touch in the tree. @@ -460,10 +449,8 @@ CREATE OPERATOR = ( equal, in pg_amop. We add the instances we need: - INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, - amopselect, amopnpages) - SELECT am.oid, opcl.oid, c.opoid, 1, - 'btreesel'::regproc, 'btreenpage'::regproc + INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) + SELECT am.oid, opcl.oid, c.opoid, 1 FROM pg_am am, pg_opclass opcl, complex_abs_ops_tmp c WHERE amname = 'btree' AND opcname = 'complex_abs_ops' AND @@ -519,13 +506,11 @@ CREATE OPERATOR = ( Now we need to add a hashing strategy to allow the type to be indexed. - We do this by using another type in pg_am but we reuse the sames ops. + We do this by using another type in pg_am but we reuse the same ops. - INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, - amopselect, amopnpages) - SELECT am.oid, opcl.oid, c.opoid, 1, - 'hashsel'::regproc, 'hashnpage'::regproc + INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) + SELECT am.oid, opcl.oid, c.opoid, 1 FROM pg_am am, pg_opclass opcl, complex_abs_ops_tmp c WHERE amname = 'hash' AND opcname = 'complex_abs_ops' AND diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index dc08d10bc3..3c286f6ec7 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.38 1999/12/30 05:04:50 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.39 2000/01/22 23:50:09 tgl Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relationId @@ -69,21 +69,6 @@ #include "access/heapam.h" #include "utils/relcache.h" -/* ---------------- - * undefine macros we aren't going to use that would otherwise - * get in our way.. delete is defined in c.h and the am's are - * defined in heapam.h - * ---------------- - */ -#undef delete -#undef aminsert -#undef amdelete -#undef ambeginscan -#undef amrescan -#undef amendscan -#undef ammarkpos -#undef amrestrpos -#undef amgettuple /* ---------------------------------------------------------------- * macros used in index_ routines @@ -358,6 +343,27 @@ index_getnext(IndexScanDesc scan, return result; } +/* ---------------- + * index_cost_estimator + * + * Fetch the amcostestimate procedure OID for an index. + * + * We could combine fetching and calling the procedure, + * as index_insert does for example; but that would require + * importing a bunch of planner/optimizer stuff into this file. + * ---------------- + */ +RegProcedure +index_cost_estimator(Relation relation) +{ + RegProcedure procedure; + + RELATION_CHECKS; + GET_REL_PROCEDURE(cost_estimator, amcostestimate); + + return procedure; +} + /* ---------------- * index_getprocid * diff --git a/src/backend/commands/variable.c b/src/backend/commands/variable.c index 031512839c..52c4ed3552 100644 --- a/src/backend/commands/variable.c +++ b/src/backend/commands/variable.c @@ -2,7 +2,7 @@ * Routines for handling of 'SET var TO', * 'SHOW var' and 'RESET var' statements. * - * $Id: variable.c,v 1.27 2000/01/15 02:59:29 petere Exp $ + * $Id: variable.c,v 1.28 2000/01/22 23:50:10 tgl Exp $ * */ @@ -14,7 +14,8 @@ #include "catalog/pg_shadow.h" #include "commands/variable.h" #include "miscadmin.h" -#include "optimizer/internal.h" +#include "optimizer/cost.h" +#include "optimizer/paths.h" #include "utils/builtins.h" #include "utils/tqual.h" #include "utils/trace.h" @@ -45,10 +46,6 @@ static bool show_XactIsoLevel(void); static bool reset_XactIsoLevel(void); static bool parse_XactIsoLevel(const char *); -extern Cost _cpu_page_weight_; -extern Cost _cpu_index_page_weight_; -extern bool _use_geqo_; -extern int32 _use_geqo_rels_; extern bool _use_keyset_query_optimizer; /* @@ -183,23 +180,23 @@ parse_geqo(const char *value) if (strcasecmp(tok, "on") == 0) { - int32 geqo_rels = GEQO_RELS; + int new_geqo_rels = GEQO_RELS; if (val != NULL) { - geqo_rels = pg_atoi(val, sizeof(int32), '\0'); - if (geqo_rels <= 1) + new_geqo_rels = pg_atoi(val, sizeof(int), '\0'); + if (new_geqo_rels <= 1) elog(ERROR, "Bad value for # of relations (%s)", val); pfree(val); } - _use_geqo_ = true; - _use_geqo_rels_ = geqo_rels; + enable_geqo = true; + geqo_rels = new_geqo_rels; } else if (strcasecmp(tok, "off") == 0) { if ((val != NULL) && (*val != '\0')) elog(ERROR, "%s does not allow a parameter", tok); - _use_geqo_ = false; + enable_geqo = false; } else elog(ERROR, "Bad value for GEQO (%s)", value); @@ -212,8 +209,8 @@ static bool show_geqo() { - if (_use_geqo_) - elog(NOTICE, "GEQO is ON beginning with %d relations", _use_geqo_rels_); + if (enable_geqo) + elog(NOTICE, "GEQO is ON beginning with %d relations", geqo_rels); else elog(NOTICE, "GEQO is OFF"); return TRUE; @@ -224,11 +221,11 @@ reset_geqo(void) { #ifdef GEQO - _use_geqo_ = true; + enable_geqo = true; #else - _use_geqo_ = false; + enable_geqo = false; #endif - _use_geqo_rels_ = GEQO_RELS; + geqo_rels = GEQO_RELS; return TRUE; } @@ -240,7 +237,7 @@ reset_geqo(void) static bool parse_cost_heap(const char *value) { - float32 res; + float64 res; if (value == NULL) { @@ -248,8 +245,8 @@ parse_cost_heap(const char *value) return TRUE; } - res = float4in((char *) value); - _cpu_page_weight_ = *res; + res = float8in((char *) value); + cpu_page_weight = *res; return TRUE; } @@ -258,14 +255,14 @@ static bool show_cost_heap() { - elog(NOTICE, "COST_HEAP is %f", _cpu_page_weight_); + elog(NOTICE, "COST_HEAP is %f", cpu_page_weight); return TRUE; } static bool reset_cost_heap() { - _cpu_page_weight_ = _CPU_PAGE_WEIGHT_; + cpu_page_weight = CPU_PAGE_WEIGHT; return TRUE; } @@ -277,7 +274,7 @@ reset_cost_heap() static bool parse_cost_index(const char *value) { - float32 res; + float64 res; if (value == NULL) { @@ -285,8 +282,8 @@ parse_cost_index(const char *value) return TRUE; } - res = float4in((char *) value); - _cpu_index_page_weight_ = *res; + res = float8in((char *) value); + cpu_index_page_weight = *res; return TRUE; } @@ -295,14 +292,14 @@ static bool show_cost_index() { - elog(NOTICE, "COST_INDEX is %f", _cpu_index_page_weight_); + elog(NOTICE, "COST_INDEX is %f", cpu_index_page_weight); return TRUE; } static bool reset_cost_index() { - _cpu_index_page_weight_ = _CPU_INDEX_PAGE_WEIGHT_; + cpu_index_page_weight = CPU_INDEX_PAGE_WEIGHT; return TRUE; } diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c index 241b8ca103..5cbea55165 100644 --- a/src/backend/nodes/copyfuncs.c +++ b/src/backend/nodes/copyfuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.100 2000/01/17 00:14:46 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.101 2000/01/22 23:50:11 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1031,6 +1031,7 @@ _copyIndexOptInfo(IndexOptInfo *from) } newnode->relam = from->relam; + newnode->amcostestimate = from->amcostestimate; newnode->indproc = from->indproc; Node_Copy(from, newnode, indpred); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 9c1219b786..8e6f68bdfd 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.78 2000/01/14 00:53:21 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.79 2000/01/22 23:50:12 tgl Exp $ * * NOTES * Most of the read functions for plan nodes are tested. (In fact, they @@ -1330,34 +1330,6 @@ _readRelOptInfo() return local_node; } -/* ---------------- - * _readIndexOptInfo - * ---------------- - */ -static IndexOptInfo * -_readIndexOptInfo() -{ - IndexOptInfo *local_node; - char *token; - int length; - - local_node = makeNode(IndexOptInfo); - - token = lsptok(NULL, &length); /* get :indexoid */ - token = lsptok(NULL, &length); /* now read it */ - local_node->indexoid = (Oid) atoi(token); - - token = lsptok(NULL, &length); /* get :pages */ - token = lsptok(NULL, &length); /* now read it */ - local_node->pages = atol(token); - - token = lsptok(NULL, &length); /* get :tuples */ - token = lsptok(NULL, &length); /* now read it */ - local_node->tuples = atof(token); - - return local_node; -} - /* ---------------- * _readTargetEntry * ---------------- @@ -1900,8 +1872,6 @@ parsePlanString(void) return_value = _readEState(); else if (length == 10 && strncmp(token, "RELOPTINFO", length) == 0) return_value = _readRelOptInfo(); - else if (length == 12 && strncmp(token, "INDEXOPTINFO", length) == 0) - return_value = _readIndexOptInfo(); else if (length == 11 && strncmp(token, "TARGETENTRY", length) == 0) return_value = _readTargetEntry(); else if (length == 3 && strncmp(token, "RTE", length) == 0) diff --git a/src/backend/optimizer/path/_deadcode/xfunc.c b/src/backend/optimizer/path/_deadcode/xfunc.c index 771cec3ecd..82c26cee5f 100644 --- a/src/backend/optimizer/path/_deadcode/xfunc.c +++ b/src/backend/optimizer/path/_deadcode/xfunc.c @@ -9,7 +9,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/xfunc.c,v 1.11 1999/11/22 17:56:10 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/_deadcode/Attic/xfunc.c,v 1.12 2000/01/22 23:50:13 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1100,27 +1100,27 @@ xfunc_expense_per_tuple(JoinPath joinnode, int whichchild) if (IsA(joinnode, HashPath)) { if (whichchild == INNER) - return (1 + _CPU_PAGE_WEIGHT_) * outers_per_page / NBuffers; + return (1 + cpu_page_weight) * outers_per_page / NBuffers; else - return (((1 + _CPU_PAGE_WEIGHT_) * outers_per_page / NBuffers) - + _CPU_PAGE_WEIGHT_ + return (((1 + cpu_page_weight) * outers_per_page / NBuffers) + + cpu_page_weight / xfunc_card_product(get_relids(innerrel))); } else if (IsA(joinnode, MergePath)) { /* assumes sort exists, and costs one (I/O + CPU) per tuple */ if (whichchild == INNER) - return ((2 * _CPU_PAGE_WEIGHT_ + 1) + return ((2 * cpu_page_weight + 1) / xfunc_card_product(get_relids(outerrel))); else - return ((2 * _CPU_PAGE_WEIGHT_ + 1) + return ((2 * cpu_page_weight + 1) / xfunc_card_product(get_relids(innerrel))); } else /* nestloop */ { Assert(IsA(joinnode, JoinPath)); - return _CPU_PAGE_WEIGHT_; + return cpu_page_weight; } } diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c index 1e357d4b8f..5cae7651ee 100644 --- a/src/backend/optimizer/path/allpaths.c +++ b/src/backend/optimizer/path/allpaths.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.55 2000/01/09 00:26:29 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/allpaths.c,v 1.56 2000/01/22 23:50:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,13 +21,12 @@ #include "optimizer/paths.h" #ifdef GEQO -bool _use_geqo_ = true; - +bool enable_geqo = true; #else -bool _use_geqo_ = false; - +bool enable_geqo = false; #endif -int32 _use_geqo_rels_ = GEQO_RELS; + +int geqo_rels = GEQO_RELS; static void set_base_rel_pathlist(Query *root, List *rels); @@ -165,11 +164,11 @@ make_one_rel_by_joins(Query *root, List *rels, int levels_needed) * genetic query optimizer entry point * * * *******************************************/ - if ((_use_geqo_) && length(root->base_rel_list) >= _use_geqo_rels_) + if (enable_geqo && length(root->base_rel_list) >= geqo_rels) return geqo(root); /******************************************* - * rest will be deprecated in case of GEQO * + * rest will be skipped in case of GEQO * *******************************************/ while (--levels_needed) diff --git a/src/backend/optimizer/path/costsize.c b/src/backend/optimizer/path/costsize.c index 8261e17c02..5c0f54a73e 100644 --- a/src/backend/optimizer/path/costsize.c +++ b/src/backend/optimizer/path/costsize.c @@ -5,20 +5,20 @@ * * Path costs are measured in units of disk accesses: one page fetch * has cost 1. The other primitive unit is the CPU time required to - * process one tuple, which we set at "_cpu_page_weight_" of a page + * process one tuple, which we set at "cpu_page_weight" of a page * fetch. Obviously, the CPU time per tuple depends on the query * involved, but the relative CPU and disk speeds of a given platform * are so variable that we are lucky if we can get useful numbers - * at all. _cpu_page_weight_ is user-settable, in case a particular + * at all. cpu_page_weight is user-settable, in case a particular * user is clueful enough to have a better-than-default estimate - * of the ratio for his platform. There is also _cpu_index_page_weight_, + * of the ratio for his platform. There is also cpu_index_page_weight, * the cost to process a tuple of an index during an index scan. * * * Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.47 2000/01/09 00:26:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.48 2000/01/22 23:50:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -44,6 +44,20 @@ #include "utils/lsyscache.h" +Cost cpu_page_weight = CPU_PAGE_WEIGHT; +Cost cpu_index_page_weight = CPU_INDEX_PAGE_WEIGHT; + +Cost disable_cost = 100000000.0; + +bool enable_seqscan = true; +bool enable_indexscan = true; +bool enable_tidscan = true; +bool enable_sort = true; +bool enable_nestloop = true; +bool enable_mergejoin = true; +bool enable_hashjoin = true; + + static void set_rel_width(Query *root, RelOptInfo *rel); static int compute_attribute_width(TargetEntry *tlistentry); static double relation_byte_size(double tuples, int width); @@ -51,19 +65,6 @@ static double page_size(double tuples, int width); static double base_log(double x, double b); -Cost _cpu_page_weight_ = _CPU_PAGE_WEIGHT_; -Cost _cpu_index_page_weight_ = _CPU_INDEX_PAGE_WEIGHT_; - -Cost _disable_cost_ = 100000000.0; - -bool _enable_seqscan_ = true; -bool _enable_indexscan_ = true; -bool _enable_sort_ = true; -bool _enable_nestloop_ = true; -bool _enable_mergejoin_ = true; -bool _enable_hashjoin_ = true; -bool _enable_tidscan_ = true; - /* * cost_seqscan * Determines and returns the cost of scanning a relation sequentially. @@ -84,8 +85,8 @@ cost_seqscan(RelOptInfo *baserel) /* Should only be applied to base relations */ Assert(length(baserel->relids) == 1); - if (!_enable_seqscan_) - temp += _disable_cost_; + if (!enable_seqscan) + temp += disable_cost; if (lfirsti(baserel->relids) < 0) { @@ -97,7 +98,7 @@ cost_seqscan(RelOptInfo *baserel) else { temp += baserel->pages; - temp += _cpu_page_weight_ * baserel->tuples; + temp += cpu_page_weight * baserel->tuples; } Assert(temp >= 0); @@ -109,58 +110,54 @@ cost_seqscan(RelOptInfo *baserel) * cost_index * Determines and returns the cost of scanning a relation using an index. * - * disk = expected-index-pages + expected-data-pages - * cpu = CPU-INDEX-PAGE-WEIGHT * expected-index-tuples + - * CPU-PAGE-WEIGHT * expected-data-tuples + * NOTE: an indexscan plan node can actually represent several passes, + * but here we consider the cost of just one pass. * + * 'root' is the query root * 'baserel' is the base relation the index is for * 'index' is the index to be used - * 'expected_indexpages' is the estimated number of index pages that will - * be touched in the scan (this is computed by index-type-specific code) - * 'selec' is the selectivity of the index, ie, the fraction of base-relation - * tuples that we will have to fetch and examine + * 'indexQuals' is the list of applicable qual clauses (implicit AND semantics) * 'is_injoin' is T if we are considering using the index scan as the inside * of a nestloop join. * - * NOTE: 'selec' should be calculated on the basis of indexqual conditions - * only. Any additional quals evaluated as qpquals may reduce the number - * of returned tuples, but they won't reduce the number of tuples we have - * to fetch from the table, so they don't reduce the scan cost. + * NOTE: 'indexQuals' must contain only clauses usable as index restrictions. + * Any additional quals evaluated as qpquals may reduce the number of returned + * tuples, but they won't reduce the number of tuples we have to fetch from + * the table, so they don't reduce the scan cost. */ Cost -cost_index(RelOptInfo *baserel, +cost_index(Query *root, + RelOptInfo *baserel, IndexOptInfo *index, - long expected_indexpages, - Selectivity selec, + List *indexQuals, bool is_injoin) { Cost temp = 0; - double reltuples = selec * baserel->tuples; - double indextuples = selec * index->tuples; + Cost indexAccessCost; + Selectivity indexSelectivity; + double reltuples; double relpages; /* Should only be applied to base relations */ Assert(IsA(baserel, RelOptInfo) && IsA(index, IndexOptInfo)); Assert(length(baserel->relids) == 1); - if (!_enable_indexscan_ && !is_injoin) - temp += _disable_cost_; + if (!enable_indexscan && !is_injoin) + temp += disable_cost; /* - * We want to be sure we estimate the cost of an index scan as more - * than the cost of a sequential scan (when selec == 1.0), even if we - * don't have good stats. So, disbelieve zero index size. + * Call index-access-method-specific code to estimate the processing + * cost for scanning the index, as well as the selectivity of the index + * (ie, the fraction of main-table tuples we will have to retrieve). */ - if (expected_indexpages <= 0) - expected_indexpages = 1; - if (indextuples <= 0.0) - indextuples = 1.0; + fmgr(index->amcostestimate, root, baserel, index, indexQuals, + &indexAccessCost, &indexSelectivity); - /* expected index relation pages */ - temp += expected_indexpages; + /* all costs for touching index itself included here */ + temp += indexAccessCost; /*-------------------- - * expected base relation pages + * Estimate number of main-table tuples and pages touched. * * Worst case is that each tuple the index tells us to fetch comes * from a different base-rel page, in which case the I/O cost would be @@ -178,6 +175,8 @@ cost_index(RelOptInfo *baserel, * So, we guess-and-hope that these sources of error will more or less * balance out. * + * XXX need to add a penalty for nonsequential page fetches. + * * XXX if the relation has recently been "clustered" using this index, * then in fact the target tuples will be highly nonuniformly distributed, * and we will be seriously overestimating the scan cost! Currently we @@ -186,16 +185,18 @@ cost_index(RelOptInfo *baserel, * effect. Would be nice to do better someday. *-------------------- */ + + reltuples = indexSelectivity * baserel->tuples; + relpages = reltuples; if (baserel->pages > 0 && baserel->pages < relpages) relpages = baserel->pages; + + /* disk costs for main table */ temp += relpages; - /* per index tuples */ - temp += _cpu_index_page_weight_ * indextuples; - - /* per heap tuples */ - temp += _cpu_page_weight_ * reltuples; + /* CPU costs for heap tuples */ + temp += cpu_page_weight * reltuples; Assert(temp >= 0); return temp; @@ -213,10 +214,10 @@ cost_tidscan(RelOptInfo *baserel, List *tideval) { Cost temp = 0; - if (!_enable_tidscan_) - temp += _disable_cost_; + if (!enable_tidscan) + temp += disable_cost; - temp += (1.0 + _cpu_page_weight_) * length(tideval); + temp += (1.0 + cpu_page_weight) * length(tideval); return temp; } @@ -227,7 +228,7 @@ cost_tidscan(RelOptInfo *baserel, List *tideval) * * If the total volume of data to sort is less than SortMem, we will do * an in-memory sort, which requires no I/O and about t*log2(t) tuple - * comparisons for t tuples. We use _cpu_index_page_weight as the cost + * comparisons for t tuples. We use cpu_index_page_weight as the cost * of a tuple comparison (is this reasonable, or do we need another * basic parameter?). * @@ -257,8 +258,8 @@ cost_sort(List *pathkeys, double tuples, int width) double nbytes = relation_byte_size(tuples, width); long sortmembytes = SortMem * 1024L; - if (!_enable_sort_) - temp += _disable_cost_; + if (!enable_sort) + temp += disable_cost; /* * We want to be sure the cost of a sort is never estimated as zero, @@ -268,7 +269,7 @@ cost_sort(List *pathkeys, double tuples, int width) if (tuples < 2.0) tuples = 2.0; - temp += _cpu_index_page_weight_ * tuples * base_log(tuples, 2.0); + temp += cpu_index_page_weight * tuples * base_log(tuples, 2.0); if (nbytes > sortmembytes) { @@ -298,7 +299,7 @@ cost_result(double tuples, int width) Cost temp = 0; temp += page_size(tuples, width); - temp += _cpu_page_weight_ * tuples; + temp += cpu_page_weight * tuples; Assert(temp >= 0); return temp; } @@ -321,8 +322,8 @@ cost_nestloop(Path *outer_path, { Cost temp = 0; - if (!_enable_nestloop_) - temp += _disable_cost_; + if (!enable_nestloop) + temp += disable_cost; temp += outer_path->path_cost; temp += outer_path->parent->rows * inner_path->path_cost; @@ -350,8 +351,8 @@ cost_mergejoin(Path *outer_path, { Cost temp = 0; - if (!_enable_mergejoin_) - temp += _disable_cost_; + if (!enable_mergejoin) + temp += disable_cost; /* cost of source data */ temp += outer_path->path_cost + inner_path->path_cost; @@ -372,8 +373,8 @@ cost_mergejoin(Path *outer_path, * underestimate if there are many equal-keyed tuples in either relation, * but we have no good way of estimating that... */ - temp += _cpu_page_weight_ * (outer_path->parent->rows + - inner_path->parent->rows); + temp += cpu_page_weight * (outer_path->parent->rows + + inner_path->parent->rows); Assert(temp >= 0); return temp; @@ -401,23 +402,23 @@ cost_hashjoin(Path *outer_path, inner_path->parent->width); long hashtablebytes = SortMem * 1024L; - if (!_enable_hashjoin_) - temp += _disable_cost_; + if (!enable_hashjoin) + temp += disable_cost; /* cost of source data */ temp += outer_path->path_cost + inner_path->path_cost; /* cost of computing hash function: must do it once per tuple */ - temp += _cpu_page_weight_ * (outer_path->parent->rows + - inner_path->parent->rows); + temp += cpu_page_weight * (outer_path->parent->rows + + inner_path->parent->rows); /* the number of tuple comparisons needed is the number of outer * tuples times the typical hash bucket size, which we estimate * conservatively as the inner disbursion times the inner tuple - * count. The cost per comparison is set at _cpu_index_page_weight_; + * count. The cost per comparison is set at cpu_index_page_weight; * is that reasonable, or do we need another basic parameter? */ - temp += _cpu_index_page_weight_ * outer_path->parent->rows * + temp += cpu_index_page_weight * outer_path->parent->rows * (inner_path->parent->rows * innerdisbursion); /* diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c index 3c93ee67ac..7bb4a8eaeb 100644 --- a/src/backend/optimizer/path/indxpath.c +++ b/src/backend/optimizer/path/indxpath.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.76 2000/01/09 00:26:31 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.77 2000/01/22 23:50:14 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1393,19 +1393,6 @@ index_innerjoin(Query *root, RelOptInfo *rel, IndexOptInfo *index, List *clausegroup = lfirst(i); IndexPath *pathnode = makeNode(IndexPath); List *indexquals; - long npages; - Selectivity selec; - - indexquals = get_actual_clauses(clausegroup); - /* expand special operators to indexquals the executor can handle */ - indexquals = expand_indexqual_conditions(indexquals); - - index_selectivity(root, - rel, - index, - indexquals, - &npages, - &selec); /* XXX this code ought to be merged with create_index_path? */ @@ -1413,6 +1400,10 @@ index_innerjoin(Query *root, RelOptInfo *rel, IndexOptInfo *index, pathnode->path.parent = rel; pathnode->path.pathkeys = build_index_pathkeys(root, rel, index); + indexquals = get_actual_clauses(clausegroup); + /* expand special operators to indexquals the executor can handle */ + indexquals = expand_indexqual_conditions(indexquals); + /* Note that we are making a pathnode for a single-scan indexscan; * therefore, both indexid and indexqual should be single-element * lists. @@ -1423,8 +1414,7 @@ index_innerjoin(Query *root, RelOptInfo *rel, IndexOptInfo *index, /* joinrelids saves the rels needed on the outer side of the join */ pathnode->joinrelids = lfirst(outerrelids_list); - pathnode->path.path_cost = cost_index(rel, index, - npages, selec, + pathnode->path.path_cost = cost_index(root, rel, index, indexquals, true); path_list = lappend(path_list, pathnode); diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c index 5c7df62fa2..f29a5cc816 100644 --- a/src/backend/optimizer/path/joinpath.c +++ b/src/backend/optimizer/path/joinpath.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.47 2000/01/09 00:26:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/joinpath.c,v 1.48 2000/01/22 23:50:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -102,7 +102,7 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels) /* * Find potential mergejoin clauses. */ - if (_enable_mergejoin_) + if (enable_mergejoin) mergeclause_list = select_mergejoin_clauses(joinrel->restrictinfo); /* @@ -141,7 +141,7 @@ update_rels_pathlist_for_joins(Query *root, List *joinrels) * 4. Consider paths where both outer and inner relations must be * hashed before being joined. */ - if (_enable_hashjoin_) + if (enable_hashjoin) pathlist = add_pathlist(joinrel, pathlist, hash_inner_and_outer(root, joinrel, outerrel, diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c index f5813a27a8..2831342fd8 100644 --- a/src/backend/optimizer/path/orindxpath.c +++ b/src/backend/optimizer/path/orindxpath.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.33 2000/01/09 00:26:33 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.34 2000/01/22 23:50:15 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -215,21 +215,11 @@ best_or_subclause_index(Query *root, foreach(ilist, indices) { IndexOptInfo *index = (IndexOptInfo *) lfirst(ilist); - long npages; - Selectivity selec; Cost subcost; Assert(IsA(index, IndexOptInfo)); - index_selectivity(root, - rel, - index, - indexqual, - &npages, - &selec); - - subcost = cost_index(rel, index, - npages, selec, + subcost = cost_index(root, rel, index, indexqual, false); if (first_run || subcost < *retCost) diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 7316a79461..87d321feff 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.41 2000/01/09 00:26:36 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/plan/initsplan.c,v 1.42 2000/01/22 23:50:16 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -257,9 +257,9 @@ add_join_info_to_rels(Query *root, RestrictInfo *restrictinfo, static void set_restrictinfo_joininfo(RestrictInfo *restrictinfo) { - if (_enable_mergejoin_) + if (enable_mergejoin) check_mergejoinable(restrictinfo); - if (_enable_hashjoin_) + if (enable_hashjoin) check_hashjoinable(restrictinfo); } diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c index a2551391e0..5c093acc9f 100644 --- a/src/backend/optimizer/util/pathnode.c +++ b/src/backend/optimizer/util/pathnode.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.56 2000/01/09 00:26:37 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/pathnode.c,v 1.57 2000/01/22 23:50:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -214,64 +214,26 @@ create_index_path(Query *root, List *restriction_clauses) { IndexPath *pathnode = makeNode(IndexPath); + List *indexquals; pathnode->path.pathtype = T_IndexScan; pathnode->path.parent = rel; pathnode->path.pathkeys = build_index_pathkeys(root, rel, index); + indexquals = get_actual_clauses(restriction_clauses); + /* expand special operators to indexquals the executor can handle */ + indexquals = expand_indexqual_conditions(indexquals); + /* - * Note that we are making a pathnode for a single-scan indexscan; - * therefore, both indexid and indexqual should be single-element - * lists. We initialize indexqual to contain one empty sublist, - * representing a single index traversal with no index restriction - * conditions. If we do have restriction conditions to use, they - * will get inserted below. + * We are making a pathnode for a single-scan indexscan; therefore, + * both indexid and indexqual should be single-element lists. */ pathnode->indexid = lconsi(index->indexoid, NIL); - pathnode->indexqual = lcons(NIL, NIL); + pathnode->indexqual = lcons(indexquals, NIL); pathnode->joinrelids = NIL; /* no join clauses here */ - if (restriction_clauses == NIL) - { - /* - * We have no restriction clauses, so compute scan cost using - * selectivity of 1.0. - */ - pathnode->path.path_cost = cost_index(rel, index, - index->pages, - (Selectivity) 1.0, - false); - } - else - { - /* - * Compute scan cost for the case when 'index' is used with - * restriction clause(s). Also, place indexqual in path node. - */ - List *indexquals; - long npages; - Selectivity selec; - - indexquals = get_actual_clauses(restriction_clauses); - /* expand special operators to indexquals the executor can handle */ - indexquals = expand_indexqual_conditions(indexquals); - - /* Insert qual list into 1st sublist of pathnode->indexqual; - * we already made the cons cell above, no point in wasting it... - */ - lfirst(pathnode->indexqual) = indexquals; - - index_selectivity(root, - rel, - index, - indexquals, - &npages, - &selec); - - pathnode->path.path_cost = cost_index(rel, index, - npages, selec, - false); - } + pathnode->path.path_cost = cost_index(root, rel, index, indexquals, + false); return pathnode; } diff --git a/src/backend/optimizer/util/plancat.c b/src/backend/optimizer/util/plancat.c index 6468ef528f..4c191f02b5 100644 --- a/src/backend/optimizer/util/plancat.c +++ b/src/backend/optimizer/util/plancat.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.44 2000/01/15 02:59:31 petere Exp $ + * $Header: /cvsroot/pgsql/src/backend/optimizer/util/plancat.c,v 1.45 2000/01/22 23:50:17 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -136,6 +136,7 @@ find_secondary_indexes(Query *root, Index relid) info->relam = relam; info->pages = indexRelation->rd_rel->relpages; info->tuples = indexRelation->rd_rel->reltuples; + info->amcostestimate = index_cost_estimator(indexRelation); index_close(indexRelation); /* @@ -168,216 +169,6 @@ find_secondary_indexes(Query *root, Index relid) return indexes; } -/* - * index_selectivity - * Estimate the selectivity of an index scan with the given index quals. - * - * NOTE: an indexscan plan node can actually represent several passes, - * but here we consider the cost of just one pass. - * - * 'root' is the query root - * 'rel' is the relation being scanned - * 'index' is the index to be used - * 'indexquals' is the list of qual condition exprs (implicit AND semantics) - * '*idxPages' receives an estimate of the number of index pages touched - * '*idxSelec' receives an estimate of selectivity of the scan, ie fraction - * of the relation's tuples that will be retrieved - */ -void -index_selectivity(Query *root, - RelOptInfo *rel, - IndexOptInfo *index, - List *indexquals, - long *idxPages, - Selectivity *idxSelec) -{ - int relid; - Oid baserelid, - indexrelid; - HeapTuple indRel, - indexTuple; - Form_pg_class indexrelation; - Oid relam; - Form_pg_index pgindex; - int nIndexKeys; - float64data npages, - select, - fattr_select; - bool nphack = false; - List *q; - - Assert(length(rel->relids) == 1); /* must be a base rel */ - relid = lfirsti(rel->relids); - - baserelid = getrelid(relid, root->rtable); - indexrelid = index->indexoid; - - indRel = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(indexrelid), - 0, 0, 0); - if (!HeapTupleIsValid(indRel)) - elog(ERROR, "index_selectivity: index %u not found in pg_class", - indexrelid); - indexrelation = (Form_pg_class) GETSTRUCT(indRel); - relam = indexrelation->relam; - - indexTuple = SearchSysCacheTuple(INDEXRELID, - ObjectIdGetDatum(indexrelid), - 0, 0, 0); - if (!HeapTupleIsValid(indexTuple)) - elog(ERROR, "index_selectivity: index %u not found in pg_index", - indexrelid); - pgindex = (Form_pg_index) GETSTRUCT(indexTuple); - - nIndexKeys = 1; - while (pgindex->indclass[nIndexKeys] != InvalidOid) - nIndexKeys++; - - /* - * Hack for non-functional btree npages estimation: npages = - * index_pages * selectivity_of_1st_attr_clause(s) - vadim 04/24/97 - */ - if (relam == BTREE_AM_OID && pgindex->indproc == InvalidOid) - nphack = true; - - npages = 0.0; - select = 1.0; - fattr_select = 1.0; - - foreach(q, indexquals) - { - Node *expr = (Node *) lfirst(q); - Oid opno; - int dummyrelid; - AttrNumber attno; - Datum value; - int flag; - Oid indclass; - HeapTuple amopTuple; - Form_pg_amop amop; - float64 amopnpages, - amopselect; - - /* - * Extract info from clause. - */ - if (is_opclause(expr)) - opno = ((Oper *) ((Expr *) expr)->oper)->opno; - else - opno = InvalidOid; - get_relattval(expr, relid, &dummyrelid, &attno, &value, &flag); - - /* - * Find the AM class for this key. - */ - if (pgindex->indproc != InvalidOid) - { - /* - * Functional index: AM class is the first one defined since - * functional indices have exactly one key. - */ - indclass = pgindex->indclass[0]; - } - else - { - int i; - indclass = InvalidOid; - for (i = 0; pgindex->indkey[i]; i++) - { - if (attno == pgindex->indkey[i]) - { - indclass = pgindex->indclass[i]; - break; - } - } - } - if (!OidIsValid(indclass)) - { - /* - * Presumably this means that we are using a functional index - * clause and so had no variable to match to the index key ... - * if not we are in trouble. - */ - elog(NOTICE, "index_selectivity: no key %d in index %u", - attno, indexrelid); - continue; - } - - amopTuple = SearchSysCacheTuple(AMOPOPID, - ObjectIdGetDatum(indclass), - ObjectIdGetDatum(opno), - ObjectIdGetDatum(relam), - 0); - if (!HeapTupleIsValid(amopTuple)) - { - /* - * We might get here because indxpath.c selected a binary- - * compatible index. Try again with the compatible operator. - */ - if (opno != InvalidOid) - { - opno = indexable_operator((Expr *) expr, indclass, relam, - ((flag & SEL_RIGHT) != 0)); - amopTuple = SearchSysCacheTuple(AMOPOPID, - ObjectIdGetDatum(indclass), - ObjectIdGetDatum(opno), - ObjectIdGetDatum(relam), - 0); - } - if (!HeapTupleIsValid(amopTuple)) - elog(ERROR, "index_selectivity: no amop %u %u %u", - indclass, opno, relam); - } - amop = (Form_pg_amop) GETSTRUCT(amopTuple); - - if (!nphack) - { - amopnpages = (float64) fmgr(amop->amopnpages, - (char *) opno, - (char *) baserelid, - (char *) (int) attno, - (char *) value, - (char *) flag, - (char *) nIndexKeys, - (char *) indexrelid); - if (PointerIsValid(amopnpages)) - npages += *amopnpages; - } - - amopselect = (float64) fmgr(amop->amopselect, - (char *) opno, - (char *) baserelid, - (char *) (int) attno, - (char *) value, - (char *) flag, - (char *) nIndexKeys, - (char *) indexrelid); - if (PointerIsValid(amopselect)) - { - select *= *amopselect; - if (nphack && attno == pgindex->indkey[0]) - fattr_select *= *amopselect; - } - } - - /* - * Estimation of npages below is hack of course, but it's better than - * it was before. - vadim 04/09/97 - */ - if (nphack) - { - npages = fattr_select * indexrelation->relpages; - *idxPages = (long) ceil((double) npages); - } - else - { - if (nIndexKeys > 1) - npages = npages / (1.0 + nIndexKeys); - *idxPages = (long) ceil((double) (npages / nIndexKeys)); - } - *idxSelec = select; -} - /* * restriction_selectivity * diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 338d93a7ff..fb226fa41a 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -7,7 +7,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.139 2000/01/09 12:17:33 ishii Exp $ + * $Header: /cvsroot/pgsql/src/backend/tcop/postgres.c,v 1.140 2000/01/22 23:50:18 tgl Exp $ * * NOTES * this is the "main" module of the postgres backend and @@ -1055,19 +1055,22 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) switch (optarg[0]) { case 's': /* seqscan */ - _enable_seqscan_ = false; + enable_seqscan = false; break; case 'i': /* indexscan */ - _enable_indexscan_ = false; + enable_indexscan = false; + break; + case 't': /* tidscan */ + enable_tidscan = false; break; case 'n': /* nestloop */ - _enable_nestloop_ = false; + enable_nestloop = false; break; case 'm': /* mergejoin */ - _enable_mergejoin_ = false; + enable_mergejoin = false; break; case 'h': /* hashjoin */ - _enable_hashjoin_ = false; + enable_hashjoin = false; break; default: errs++; @@ -1512,7 +1515,7 @@ PostgresMain(int argc, char *argv[], int real_argc, char *real_argv[]) if (!IsUnderPostmaster) { puts("\nPOSTGRES backend interactive interface "); - puts("$Revision: 1.139 $ $Date: 2000/01/09 12:17:33 $\n"); + puts("$Revision: 1.140 $ $Date: 2000/01/22 23:50:18 $\n"); } /* diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 7ec3e4dc1b..f1c458b761 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -1,16 +1,20 @@ /*------------------------------------------------------------------------- * * selfuncs.c - * Selectivity functions for system catalogs and builtin types + * Selectivity functions and index cost estimation functions for + * standard operators and index access methods. * - * These routines are registered in the operator catalog in the - * "oprrest" and "oprjoin" attributes. + * Selectivity routines are registered in the pg_operator catalog + * in the "oprrest" and "oprjoin" attributes. + * + * Index cost functions are registered in the pg_am catalog + * in the "amcostestimate" attribute. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.48 2000/01/15 22:43:24 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.49 2000/01/22 23:50:20 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -23,6 +27,7 @@ #include "catalog/pg_proc.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" +#include "optimizer/cost.h" #include "parser/parse_func.h" #include "parser/parse_oper.h" #include "utils/builtins.h" @@ -700,349 +705,74 @@ getattstatistics(Oid relid, AttrNumber attnum, Oid opid, Oid typid, return true; } -float64 -btreesel(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) +/*------------------------------------------------------------------------- + * + * Index cost estimation functions + * + * genericcostestimate is a general-purpose estimator for use when we + * don't have any better idea about how to estimate. Index-type-specific + * knowledge can be incorporated in the type-specific routines. + * + *------------------------------------------------------------------------- + */ + +static void +genericcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, Selectivity *indexSelectivity) { - float64 result; + double numIndexTuples; + double numIndexPages; - if (FunctionalSelectivity(nIndexKeys, attributeNumber)) - { + /* Estimate the fraction of main-table tuples that will be visited */ + *indexSelectivity = clauselist_selec(root, indexQuals); - /* - * Need to call the functions selectivity function here. For now - * simply assume it's 1/3 since functions don't currently have - * selectivity functions - */ - result = (float64) palloc(sizeof(float64data)); - *result = 1.0 / 3.0; - } - else - { - RegProcedure oprrest = get_oprrest(operatorObjectId); + /* Estimate the number of index tuples that will be visited */ + numIndexTuples = *indexSelectivity * index->tuples; - /* - * Operators used for indexes should have selectivity estimators. - * (An alternative is to default to 0.5, as the optimizer does in - * dealing with operators occurring in WHERE clauses, but if you - * are going to the trouble of making index support you probably - * don't want to miss the benefits of a good selectivity estimate.) - */ - if (!oprrest) - { -#if 1 - /* - * XXX temporary fix for 6.5: rtree operators are missing their - * selectivity estimators, so return a default estimate instead. - * Ugh. - */ - result = (float64) palloc(sizeof(float64data)); - *result = 0.5; -#else - elog(ERROR, - "Operator %u must have a restriction selectivity estimator to be used in an index", - operatorObjectId); -#endif - } - else - result = (float64) fmgr(oprrest, - (char *) operatorObjectId, - (char *) indrelid, - (char *) (int) attributeNumber, - (char *) constValue, - (char *) constFlag, - NULL); - } + /* Estimate the number of index pages that will be retrieved */ + numIndexPages = *indexSelectivity * index->pages; - if (!PointerIsValid(result)) - elog(ERROR, "Btree Selectivity: bad pointer"); - if (*result < 0.0 || *result > 1.0) - elog(ERROR, "Btree Selectivity: bad value %f", *result); - - return result; + /* Compute the index access cost */ + *indexAccessCost = numIndexPages + cpu_index_page_weight * numIndexTuples; } -float64 -btreenpage(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) +/* + * For first cut, just use generic function for all index types. + */ + +void +btcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, Selectivity *indexSelectivity) { - float64 temp, - result; - float64data tempData; - HeapTuple atp; - int npage; - - if (FunctionalSelectivity(nIndexKeys, attributeNumber)) - { - - /* - * Need to call the functions selectivity function here. For now - * simply assume it's 1/3 since functions don't currently have - * selectivity functions - */ - tempData = 1.0 / 3.0; - temp = &tempData; - } - else - { - RegProcedure oprrest = get_oprrest(operatorObjectId); - - /* - * Operators used for indexes should have selectivity estimators. - * (An alternative is to default to 0.5, as the optimizer does in - * dealing with operators occurring in WHERE clauses, but if you - * are going to the trouble of making index support you probably - * don't want to miss the benefits of a good selectivity estimate.) - */ - if (!oprrest) - { -#if 1 - /* - * XXX temporary fix for 6.5: rtree operators are missing their - * selectivity estimators, so return a default estimate instead. - * Ugh. - */ - tempData = 0.5; - temp = &tempData; -#else - elog(ERROR, - "Operator %u must have a restriction selectivity estimator to be used in an index", - operatorObjectId); -#endif - } - else - temp = (float64) fmgr(oprrest, - (char *) operatorObjectId, - (char *) indrelid, - (char *) (int) attributeNumber, - (char *) constValue, - (char *) constFlag, - NULL); - } - - atp = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(indexrelid), - 0, 0, 0); - if (!HeapTupleIsValid(atp)) - { - elog(ERROR, "btreenpage: no index tuple %u", indexrelid); - return 0; - } - - npage = ((Form_pg_class) GETSTRUCT(atp))->relpages; - result = (float64) palloc(sizeof(float64data)); - *result = *temp * npage; - return result; + genericcostestimate(root, rel, index, indexQuals, + indexAccessCost, indexSelectivity); } -float64 -hashsel(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) +void +rtcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, Selectivity *indexSelectivity) { - - float64 result; - float64data resultData; - HeapTuple atp; - int ntuples; - - if (FunctionalSelectivity(nIndexKeys, attributeNumber)) - { - - /* - * Need to call the functions selectivity function here. For now - * simply use 1/Number of Tuples since functions don't currently - * have selectivity functions - */ - - atp = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(indexrelid), - 0, 0, 0); - if (!HeapTupleIsValid(atp)) - { - elog(ERROR, "hashsel: no index tuple %u", indexrelid); - return 0; - } - ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; - if (ntuples > 0) - resultData = 1.0 / (float64data) ntuples; - else - resultData = (float64data) (1.0 / 100.0); - result = &resultData; - - } - else - { - RegProcedure oprrest = get_oprrest(operatorObjectId); - - /* - * Operators used for indexes should have selectivity estimators. - * (An alternative is to default to 0.5, as the optimizer does in - * dealing with operators occurring in WHERE clauses, but if you - * are going to the trouble of making index support you probably - * don't want to miss the benefits of a good selectivity estimate.) - */ - if (!oprrest) - elog(ERROR, - "Operator %u must have a restriction selectivity estimator to be used in a hash index", - operatorObjectId); - - result = (float64) fmgr(oprrest, - (char *) operatorObjectId, - (char *) indrelid, - (char *) (int) attributeNumber, - (char *) constValue, - (char *) constFlag, - NULL); - } - - if (!PointerIsValid(result)) - elog(ERROR, "Hash Table Selectivity: bad pointer"); - if (*result < 0.0 || *result > 1.0) - elog(ERROR, "Hash Table Selectivity: bad value %f", *result); - - return result; - - + genericcostestimate(root, rel, index, indexQuals, + indexAccessCost, indexSelectivity); } -float64 -hashnpage(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) +void +hashcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, Selectivity *indexSelectivity) { - float64 temp, - result; - float64data tempData; - HeapTuple atp; - int npage; - int ntuples; - - atp = SearchSysCacheTuple(RELOID, - ObjectIdGetDatum(indexrelid), - 0, 0, 0); - if (!HeapTupleIsValid(atp)) - { - elog(ERROR, "hashsel: no index tuple %u", indexrelid); - return 0; - } - - - if (FunctionalSelectivity(nIndexKeys, attributeNumber)) - { - - /* - * Need to call the functions selectivity function here. For now, - * use 1/Number of Tuples since functions don't currently have - * selectivity functions - */ - - ntuples = ((Form_pg_class) GETSTRUCT(atp))->reltuples; - if (ntuples > 0) - tempData = 1.0 / (float64data) ntuples; - else - tempData = (float64data) (1.0 / 100.0); - temp = &tempData; - - } - else - { - RegProcedure oprrest = get_oprrest(operatorObjectId); - - /* - * Operators used for indexes should have selectivity estimators. - * (An alternative is to default to 0.5, as the optimizer does in - * dealing with operators occurring in WHERE clauses, but if you - * are going to the trouble of making index support you probably - * don't want to miss the benefits of a good selectivity estimate.) - */ - if (!oprrest) - elog(ERROR, - "Operator %u must have a restriction selectivity estimator to be used in a hash index", - operatorObjectId); - - temp = (float64) fmgr(oprrest, - (char *) operatorObjectId, - (char *) indrelid, - (char *) (int) attributeNumber, - (char *) constValue, - (char *) constFlag, - NULL); - } - - npage = ((Form_pg_class) GETSTRUCT(atp))->relpages; - result = (float64) palloc(sizeof(float64data)); - *result = *temp * npage; - return result; + genericcostestimate(root, rel, index, indexQuals, + indexAccessCost, indexSelectivity); } - -float64 -rtsel(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) +void +gistcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, Selectivity *indexSelectivity) { - return (btreesel(operatorObjectId, indrelid, attributeNumber, - constValue, constFlag, nIndexKeys, indexrelid)); -} - -float64 -rtnpage(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) -{ - return (btreenpage(operatorObjectId, indrelid, attributeNumber, - constValue, constFlag, nIndexKeys, indexrelid)); -} - -float64 -gistsel(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) -{ - return (btreesel(operatorObjectId, indrelid, attributeNumber, - constValue, constFlag, nIndexKeys, indexrelid)); -} - -float64 -gistnpage(Oid operatorObjectId, - Oid indrelid, - AttrNumber attributeNumber, - char *constValue, - int32 constFlag, - int32 nIndexKeys, - Oid indexrelid) -{ - return (btreenpage(operatorObjectId, indrelid, attributeNumber, - constValue, constFlag, nIndexKeys, indexrelid)); + genericcostestimate(root, rel, index, indexQuals, + indexAccessCost, indexSelectivity); } diff --git a/src/include/access/genam.h b/src/include/access/genam.h index 76200f215e..81b38da6cc 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: genam.h,v 1.21 1999/12/30 05:05:13 tgl Exp $ + * $Id: genam.h,v 1.22 2000/01/22 23:50:22 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -38,6 +38,7 @@ extern void index_markpos(IndexScanDesc scan); extern void index_restrpos(IndexScanDesc scan); extern RetrieveIndexResult index_getnext(IndexScanDesc scan, ScanDirection direction); +extern RegProcedure index_cost_estimator(Relation relation); extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum, uint16 procnum); extern Datum GetIndexValue(HeapTuple tuple, TupleDesc hTupDesc, diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index eca72916b8..d706d1f20a 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -36,7 +36,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: catversion.h,v 1.8 2000/01/18 05:08:29 ishii Exp $ + * $Id: catversion.h,v 1.9 2000/01/22 23:50:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -52,6 +52,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200001171 +#define CATALOG_VERSION_NO 200001221 #endif diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index 4ec5062ffa..2be6a7259b 100644 --- a/src/include/catalog/pg_am.h +++ b/src/include/catalog/pg_am.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pg_am.h,v 1.11 1999/02/13 23:21:04 momjian Exp $ + * $Id: pg_am.h,v 1.12 2000/01/22 23:50:23 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -57,6 +57,7 @@ CATALOG(pg_am) regproc ambuild; regproc amcreate; regproc amdestroy; + regproc amcostestimate; } FormData_pg_am; /* ---------------- @@ -70,7 +71,7 @@ typedef FormData_pg_am *Form_pg_am; * compiler constants for pg_am * ---------------- */ -#define Natts_pg_am 22 +#define Natts_pg_am 23 #define Anum_pg_am_amname 1 #define Anum_pg_am_amowner 2 #define Anum_pg_am_amkind 3 @@ -93,21 +94,22 @@ typedef FormData_pg_am *Form_pg_am; #define Anum_pg_am_ambuild 20 #define Anum_pg_am_amcreate 21 #define Anum_pg_am_amdestroy 22 +#define Anum_pg_am_amcostestimate 23 /* ---------------- * initial contents of pg_am * ---------------- */ -DATA(insert OID = 402 ( rtree PGUID "o" 8 3 rtgettuple rtinsert rtdelete - - - - rtbeginscan rtrescan rtendscan rtmarkpos rtrestrpos - - rtbuild - - )); +DATA(insert OID = 402 ( rtree PGUID "o" 8 3 rtgettuple rtinsert rtdelete - - - - rtbeginscan rtrescan rtendscan rtmarkpos rtrestrpos - - rtbuild - - rtcostestimate )); DESCR(""); -DATA(insert OID = 403 ( btree PGUID "o" 5 1 btgettuple btinsert btdelete - - - - btbeginscan btrescan btendscan btmarkpos btrestrpos - - btbuild - - )); +DATA(insert OID = 403 ( btree PGUID "o" 5 1 btgettuple btinsert btdelete - - - - btbeginscan btrescan btendscan btmarkpos btrestrpos - - btbuild - - btcostestimate )); DESCR(""); #define BTREE_AM_OID 403 -DATA(insert OID = 405 ( hash PGUID "o" 1 1 hashgettuple hashinsert hashdelete - - - - hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos - - hashbuild - - )); +DATA(insert OID = 405 ( hash PGUID "o" 1 1 hashgettuple hashinsert hashdelete - - - - hashbeginscan hashrescan hashendscan hashmarkpos hashrestrpos - - hashbuild - - hashcostestimate )); DESCR(""); #define HASH_AM_OID 405 -DATA(insert OID = 783 ( gist PGUID "o" 100 7 gistgettuple gistinsert gistdelete - - - - gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos - - gistbuild - - )); +DATA(insert OID = 783 ( gist PGUID "o" 100 7 gistgettuple gistinsert gistdelete - - - - gistbeginscan gistrescan gistendscan gistmarkpos gistrestrpos - - gistbuild - - gistcostestimate )); DESCR(""); #endif /* PG_AM_H */ diff --git a/src/include/catalog/pg_amop.h b/src/include/catalog/pg_amop.h index 93ed1d4693..c6c71f526f 100644 --- a/src/include/catalog/pg_amop.h +++ b/src/include/catalog/pg_amop.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pg_amop.h,v 1.27 2000/01/10 16:13:20 momjian Exp $ + * $Id: pg_amop.h,v 1.28 2000/01/22 23:50:23 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -36,8 +36,6 @@ CATALOG(pg_amop) Oid amopclaid; Oid amopopr; int2 amopstrategy; - regproc amopselect; - regproc amopnpages; } FormData_pg_amop; /* ---------------- @@ -51,14 +49,11 @@ typedef FormData_pg_amop *Form_pg_amop; * compiler constants for pg_amop * ---------------- */ -/* #define Name_pg_amop "pg_amop" */ -#define Natts_pg_amop 6 +#define Natts_pg_amop 4 #define Anum_pg_amop_amopid 1 #define Anum_pg_amop_amopclaid 2 #define Anum_pg_amop_amopopr 3 #define Anum_pg_amop_amopstrategy 4 -#define Anum_pg_amop_amopselect 5 -#define Anum_pg_amop_amopnpages 6 /* ---------------- * initial contents of pg_amop @@ -69,326 +64,326 @@ typedef FormData_pg_amop *Form_pg_amop; * rtree box_ops */ -DATA(insert OID = 0 ( 402 422 493 1 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 422 494 2 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 422 500 3 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 422 495 4 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 422 496 5 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 422 499 6 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 422 498 7 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 422 497 8 rtsel rtnpage )); +DATA(insert OID = 0 ( 402 422 493 1 )); +DATA(insert OID = 0 ( 402 422 494 2 )); +DATA(insert OID = 0 ( 402 422 500 3 )); +DATA(insert OID = 0 ( 402 422 495 4 )); +DATA(insert OID = 0 ( 402 422 496 5 )); +DATA(insert OID = 0 ( 402 422 499 6 )); +DATA(insert OID = 0 ( 402 422 498 7 )); +DATA(insert OID = 0 ( 402 422 497 8 )); /* * rtree bigbox_ops */ -DATA(insert OID = 0 ( 402 433 493 1 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 433 494 2 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 433 500 3 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 433 495 4 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 433 496 5 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 433 499 6 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 433 498 7 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 433 497 8 rtsel rtnpage )); +DATA(insert OID = 0 ( 402 433 493 1 )); +DATA(insert OID = 0 ( 402 433 494 2 )); +DATA(insert OID = 0 ( 402 433 500 3 )); +DATA(insert OID = 0 ( 402 433 495 4 )); +DATA(insert OID = 0 ( 402 433 496 5 )); +DATA(insert OID = 0 ( 402 433 499 6 )); +DATA(insert OID = 0 ( 402 433 498 7 )); +DATA(insert OID = 0 ( 402 433 497 8 )); /* * rtree poly_ops (supports polygons) */ -DATA(insert OID = 0 ( 402 434 485 1 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 434 486 2 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 434 492 3 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 434 487 4 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 434 488 5 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 434 491 6 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 434 490 7 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 434 489 8 rtsel rtnpage )); +DATA(insert OID = 0 ( 402 434 485 1 )); +DATA(insert OID = 0 ( 402 434 486 2 )); +DATA(insert OID = 0 ( 402 434 492 3 )); +DATA(insert OID = 0 ( 402 434 487 4 )); +DATA(insert OID = 0 ( 402 434 488 5 )); +DATA(insert OID = 0 ( 402 434 491 6 )); +DATA(insert OID = 0 ( 402 434 490 7 )); +DATA(insert OID = 0 ( 402 434 489 8 )); /* * rtree circle_ops (supports circles) */ -DATA(insert OID = 0 ( 402 714 1506 1 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 714 1507 2 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 714 1513 3 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 714 1508 4 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 714 1509 5 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 714 1512 6 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 714 1511 7 rtsel rtnpage )); -DATA(insert OID = 0 ( 402 714 1510 8 rtsel rtnpage )); +DATA(insert OID = 0 ( 402 714 1506 1 )); +DATA(insert OID = 0 ( 402 714 1507 2 )); +DATA(insert OID = 0 ( 402 714 1513 3 )); +DATA(insert OID = 0 ( 402 714 1508 4 )); +DATA(insert OID = 0 ( 402 714 1509 5 )); +DATA(insert OID = 0 ( 402 714 1512 6 )); +DATA(insert OID = 0 ( 402 714 1511 7 )); +DATA(insert OID = 0 ( 402 714 1510 8 )); /* * nbtree int2_ops */ -DATA(insert OID = 0 ( 403 421 95 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 421 522 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 421 94 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 421 524 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 421 520 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 421 95 1 )); +DATA(insert OID = 0 ( 403 421 522 2 )); +DATA(insert OID = 0 ( 403 421 94 3 )); +DATA(insert OID = 0 ( 403 421 524 4 )); +DATA(insert OID = 0 ( 403 421 520 5 )); /* * nbtree float8_ops */ -DATA(insert OID = 0 ( 403 423 672 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 423 673 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 423 670 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 423 675 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 423 674 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 423 672 1 )); +DATA(insert OID = 0 ( 403 423 673 2 )); +DATA(insert OID = 0 ( 403 423 670 3 )); +DATA(insert OID = 0 ( 403 423 675 4 )); +DATA(insert OID = 0 ( 403 423 674 5 )); /* * nbtree int24_ops */ -DATA(insert OID = 0 ( 403 424 534 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 424 540 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 424 532 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 424 542 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 424 536 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 424 534 1 )); +DATA(insert OID = 0 ( 403 424 540 2 )); +DATA(insert OID = 0 ( 403 424 532 3 )); +DATA(insert OID = 0 ( 403 424 542 4 )); +DATA(insert OID = 0 ( 403 424 536 5 )); /* * nbtree int42_ops */ -DATA(insert OID = 0 ( 403 425 535 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 425 541 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 425 533 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 425 543 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 425 537 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 425 535 1 )); +DATA(insert OID = 0 ( 403 425 541 2 )); +DATA(insert OID = 0 ( 403 425 533 3 )); +DATA(insert OID = 0 ( 403 425 543 4 )); +DATA(insert OID = 0 ( 403 425 537 5 )); /* * nbtree int4_ops */ -DATA(insert OID = 0 ( 403 426 97 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 426 523 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 426 96 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 426 525 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 426 521 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 426 97 1 )); +DATA(insert OID = 0 ( 403 426 523 2 )); +DATA(insert OID = 0 ( 403 426 96 3 )); +DATA(insert OID = 0 ( 403 426 525 4 )); +DATA(insert OID = 0 ( 403 426 521 5 )); /* * nbtree int8_ops */ -DATA(insert OID = 0 ( 403 754 412 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 754 414 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 754 410 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 754 415 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 754 413 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 754 412 1 )); +DATA(insert OID = 0 ( 403 754 414 2 )); +DATA(insert OID = 0 ( 403 754 410 3 )); +DATA(insert OID = 0 ( 403 754 415 4 )); +DATA(insert OID = 0 ( 403 754 413 5 )); /* * nbtree oid_ops */ -DATA(insert OID = 0 ( 403 427 609 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 427 611 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 427 607 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 427 612 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 427 610 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 427 609 1 )); +DATA(insert OID = 0 ( 403 427 611 2 )); +DATA(insert OID = 0 ( 403 427 607 3 )); +DATA(insert OID = 0 ( 403 427 612 4 )); +DATA(insert OID = 0 ( 403 427 610 5 )); /* * nbtree oidvector_ops */ -DATA(insert OID = 0 ( 403 435 645 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 435 647 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 435 649 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 435 648 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 435 646 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 435 645 1 )); +DATA(insert OID = 0 ( 403 435 647 2 )); +DATA(insert OID = 0 ( 403 435 649 3 )); +DATA(insert OID = 0 ( 403 435 648 4 )); +DATA(insert OID = 0 ( 403 435 646 5 )); /* * nbtree float4_ops */ -DATA(insert OID = 0 ( 403 428 622 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 428 624 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 428 620 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 428 625 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 428 623 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 428 622 1 )); +DATA(insert OID = 0 ( 403 428 624 2 )); +DATA(insert OID = 0 ( 403 428 620 3 )); +DATA(insert OID = 0 ( 403 428 625 4 )); +DATA(insert OID = 0 ( 403 428 623 5 )); /* * nbtree char_ops */ -DATA(insert OID = 0 ( 403 429 631 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 429 632 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 429 92 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 429 634 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 429 633 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 429 631 1 )); +DATA(insert OID = 0 ( 403 429 632 2 )); +DATA(insert OID = 0 ( 403 429 92 3 )); +DATA(insert OID = 0 ( 403 429 634 4 )); +DATA(insert OID = 0 ( 403 429 633 5 )); /* * nbtree name_ops */ -DATA(insert OID = 0 ( 403 1181 660 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1181 661 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1181 93 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1181 663 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1181 662 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 1181 660 1 )); +DATA(insert OID = 0 ( 403 1181 661 2 )); +DATA(insert OID = 0 ( 403 1181 93 3 )); +DATA(insert OID = 0 ( 403 1181 663 4 )); +DATA(insert OID = 0 ( 403 1181 662 5 )); /* * nbtree text_ops */ -DATA(insert OID = 0 ( 403 431 664 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 431 665 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 431 98 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 431 667 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 431 666 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 431 664 1 )); +DATA(insert OID = 0 ( 403 431 665 2 )); +DATA(insert OID = 0 ( 403 431 98 3 )); +DATA(insert OID = 0 ( 403 431 667 4 )); +DATA(insert OID = 0 ( 403 431 666 5 )); /* * nbtree abstime_ops */ -DATA(insert OID = 0 ( 403 432 562 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 432 564 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 432 560 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 432 565 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 432 563 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 432 562 1 )); +DATA(insert OID = 0 ( 403 432 564 2 )); +DATA(insert OID = 0 ( 403 432 560 3 )); +DATA(insert OID = 0 ( 403 432 565 4 )); +DATA(insert OID = 0 ( 403 432 563 5 )); /* * nbtree bpchar_ops */ -DATA(insert OID = 0 ( 403 1076 1058 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1076 1059 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1076 1054 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1076 1061 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1076 1060 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 1076 1058 1 )); +DATA(insert OID = 0 ( 403 1076 1059 2 )); +DATA(insert OID = 0 ( 403 1076 1054 3 )); +DATA(insert OID = 0 ( 403 1076 1061 4 )); +DATA(insert OID = 0 ( 403 1076 1060 5 )); /* * nbtree varchar_ops */ -DATA(insert OID = 0 ( 403 1077 1066 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1077 1067 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1077 1062 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1077 1069 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1077 1068 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 1077 1066 1 )); +DATA(insert OID = 0 ( 403 1077 1067 2 )); +DATA(insert OID = 0 ( 403 1077 1062 3 )); +DATA(insert OID = 0 ( 403 1077 1069 4 )); +DATA(insert OID = 0 ( 403 1077 1068 5 )); /* * nbtree date_ops */ -DATA(insert OID = 0 ( 403 1114 1095 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1114 1096 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1114 1093 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1114 1098 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1114 1097 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 1114 1095 1 )); +DATA(insert OID = 0 ( 403 1114 1096 2 )); +DATA(insert OID = 0 ( 403 1114 1093 3 )); +DATA(insert OID = 0 ( 403 1114 1098 4 )); +DATA(insert OID = 0 ( 403 1114 1097 5 )); /* * nbtree time_ops */ -DATA(insert OID = 0 ( 403 1115 1110 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1115 1111 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1115 1108 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1115 1113 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1115 1112 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 1115 1110 1 )); +DATA(insert OID = 0 ( 403 1115 1111 2 )); +DATA(insert OID = 0 ( 403 1115 1108 3 )); +DATA(insert OID = 0 ( 403 1115 1113 4 )); +DATA(insert OID = 0 ( 403 1115 1112 5 )); /* * nbtree datetime_ops */ -DATA(insert OID = 0 ( 403 1312 1322 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1312 1323 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1312 1320 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1312 1325 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1312 1324 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 1312 1322 1 )); +DATA(insert OID = 0 ( 403 1312 1323 2 )); +DATA(insert OID = 0 ( 403 1312 1320 3 )); +DATA(insert OID = 0 ( 403 1312 1325 4 )); +DATA(insert OID = 0 ( 403 1312 1324 5 )); /* * nbtree timespan_ops */ -DATA(insert OID = 0 ( 403 1313 1332 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1313 1333 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1313 1330 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1313 1335 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1313 1334 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 1313 1332 1 )); +DATA(insert OID = 0 ( 403 1313 1333 2 )); +DATA(insert OID = 0 ( 403 1313 1330 3 )); +DATA(insert OID = 0 ( 403 1313 1335 4 )); +DATA(insert OID = 0 ( 403 1313 1334 5 )); /* * nbtree macaddr */ -DATA(insert OID = 0 ( 403 810 1222 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 810 1223 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 810 1220 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 810 1225 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 810 1224 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 810 1222 1 )); +DATA(insert OID = 0 ( 403 810 1223 2 )); +DATA(insert OID = 0 ( 403 810 1220 3 )); +DATA(insert OID = 0 ( 403 810 1225 4 )); +DATA(insert OID = 0 ( 403 810 1224 5 )); /* * nbtree inet */ -DATA(insert OID = 0 ( 403 935 1203 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 935 1204 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 935 1201 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 935 1206 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 935 1205 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 935 1203 1 )); +DATA(insert OID = 0 ( 403 935 1204 2 )); +DATA(insert OID = 0 ( 403 935 1201 3 )); +DATA(insert OID = 0 ( 403 935 1206 4 )); +DATA(insert OID = 0 ( 403 935 1205 5 )); /* * nbtree cidr */ -DATA(insert OID = 0 ( 403 652 822 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 652 823 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 652 820 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 652 825 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 652 824 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 652 822 1 )); +DATA(insert OID = 0 ( 403 652 823 2 )); +DATA(insert OID = 0 ( 403 652 820 3 )); +DATA(insert OID = 0 ( 403 652 825 4 )); +DATA(insert OID = 0 ( 403 652 824 5 )); /* * nbtree numeric */ -DATA(insert OID = 0 ( 403 1768 1754 1 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1768 1755 2 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1768 1752 3 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1768 1757 4 btreesel btreenpage )); -DATA(insert OID = 0 ( 403 1768 1756 5 btreesel btreenpage )); +DATA(insert OID = 0 ( 403 1768 1754 1 )); +DATA(insert OID = 0 ( 403 1768 1755 2 )); +DATA(insert OID = 0 ( 403 1768 1752 3 )); +DATA(insert OID = 0 ( 403 1768 1757 4 )); +DATA(insert OID = 0 ( 403 1768 1756 5 )); /* * hash table _ops */ /* int2_ops */ -DATA(insert OID = 0 ( 405 421 94 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 421 94 1 )); /* float8_ops */ -DATA(insert OID = 0 ( 405 423 670 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 423 670 1 )); /* int4_ops */ -DATA(insert OID = 0 ( 405 426 96 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 426 96 1 )); /* int8_ops */ -DATA(insert OID = 0 ( 405 754 410 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 754 410 1 )); /* oid_ops */ -DATA(insert OID = 0 ( 405 427 607 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 427 607 1 )); /* oidvector_ops */ -DATA(insert OID = 0 ( 405 435 649 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 435 649 1 )); /* float4_ops */ -DATA(insert OID = 0 ( 405 428 620 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 428 620 1 )); /* char_ops */ -DATA(insert OID = 0 ( 405 429 92 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 429 92 1 )); /* name_ops */ -DATA(insert OID = 0 ( 405 1181 93 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 1181 93 1 )); /* text_ops */ -DATA(insert OID = 0 ( 405 431 98 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 431 98 1 )); /* bpchar_ops */ -DATA(insert OID = 0 ( 405 1076 1054 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 1076 1054 1 )); /* varchar_ops */ -DATA(insert OID = 0 ( 405 1077 1062 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 1077 1062 1 )); /* date_ops */ -DATA(insert OID = 0 ( 405 1114 1093 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 1114 1093 1 )); /* time_ops */ -DATA(insert OID = 0 ( 405 1115 1108 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 1115 1108 1 )); /* datetime_ops */ -DATA(insert OID = 0 ( 405 1312 1320 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 1312 1320 1 )); /* timespan_ops */ -DATA(insert OID = 0 ( 405 1313 1330 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 1313 1330 1 )); /* macaddr_ops */ -DATA(insert OID = 0 ( 405 810 1220 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 810 1220 1 )); /* inet_ops */ -DATA(insert OID = 0 ( 405 935 1201 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 935 1201 1 )); /* cidr_ops */ -DATA(insert OID = 0 ( 405 652 820 1 hashsel hashnpage )); +DATA(insert OID = 0 ( 405 652 820 1 )); #endif /* PG_AMOP_H */ diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 583d53e081..0fffcf3657 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: pg_proc.h,v 1.114 2000/01/18 05:08:29 ishii Exp $ + * $Id: pg_proc.h,v 1.115 2000/01/22 23:50:23 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -211,17 +211,13 @@ DESCR("not equal"); DATA(insert OID = 89 ( version PGUID 11 f t f 0 f 25 "" 100 0 0 100 version - )); DESCR("PostgreSQL version string"); -DATA(insert OID = 1265 ( rtsel PGUID 11 f t f 7 f 701 "26 26 21 0 23 23 26" 100 0 0 100 rtsel - )); -DESCR("r-tree"); -DATA(insert OID = 1266 ( rtnpage PGUID 11 f t f 7 f 701 "26 26 21 0 23 23 26" 100 0 0 100 rtnpage - )); -DESCR("r-tree"); -DATA(insert OID = 1268 ( btreesel PGUID 11 f t f 7 f 701 "26 26 21 0 23 23 26" 100 0 0 100 btreesel - )); -DESCR("btree selectivity"); +DATA(insert OID = 1265 ( rtcostestimate PGUID 11 f t f 6 f 0 "0 0 0 0 0 0" 100 0 0 100 rtcostestimate - )); +DESCR("r-tree cost estimator"); +DATA(insert OID = 1268 ( btcostestimate PGUID 11 f t f 6 f 0 "0 0 0 0 0 0" 100 0 0 100 btcostestimate - )); +DESCR("btree cost estimator"); /* OIDS 100 - 199 */ -DATA(insert OID = 1270 ( btreenpage PGUID 11 f t f 7 f 701 "26 26 21 0 23 23 26" 100 0 0 100 btreenpage - )); -DESCR("btree"); DATA(insert OID = 1272 ( eqsel PGUID 11 f t f 5 f 701 "26 26 21 0 23" 100 0 0 100 eqsel - )); DESCR("general selectivity"); DATA(insert OID = 102 ( neqsel PGUID 11 f t f 5 f 701 "26 26 21 0 23" 100 0 0 100 neqsel - )); @@ -799,10 +795,8 @@ DESCR("convert name to char()"); DATA(insert OID = 409 ( bpchar_name PGUID 11 f t t 1 f 19 "1042" 100 0 0 100 bpchar_name - )); DESCR("convert char() to name"); -DATA(insert OID = 438 ( hashsel PGUID 11 f t f 7 f 701 "26 26 21 0 23 23 26" 100 0 0 100 hashsel - )); -DESCR("selectivity"); -DATA(insert OID = 439 ( hashnpage PGUID 11 f t f 7 f 701 "26 26 21 0 23 23 26" 100 0 0 100 hashnpage - )); -DESCR("hash"); +DATA(insert OID = 438 ( hashcostestimate PGUID 11 f t f 6 f 0 "0 0 0 0 0 0" 100 0 0 100 hashcostestimate - )); +DESCR("hash index cost estimator"); DATA(insert OID = 440 ( hashgettuple PGUID 11 f t f 2 f 23 "0" 100 0 0 100 hashgettuple - )); DESCR("hash(internal)"); @@ -1036,10 +1030,8 @@ DESCR("larger of two"); DATA(insert OID = 771 ( int2smaller PGUID 11 f t t 2 f 21 "21 21" 100 0 0 100 int2smaller - )); DESCR("smaller of two"); -DATA(insert OID = 772 ( gistsel PGUID 11 f t f 7 f 701 "26 26 21 0 23 23 26" 100 0 0 100 gistsel - )); -DESCR("gist selectivity"); -DATA(insert OID = 773 ( gistnpage PGUID 11 f t f 7 f 701 "26 26 21 0 23 23 26" 100 0 0 100 gistnpage - )); -DESCR("gist"); +DATA(insert OID = 772 ( gistcostestimate PGUID 11 f t f 6 f 0 "0 0 0 0 0 0" 100 0 0 100 gistcostestimate - )); +DESCR("gist cost estimator"); DATA(insert OID = 774 ( gistgettuple PGUID 11 f t f 2 f 23 "0" 100 0 0 100 gistgettuple - )); DESCR("gist(internal)"); DATA(insert OID = 775 ( gistinsert PGUID 11 f t f 5 f 23 "0" 100 0 0 100 gistinsert - )); diff --git a/src/include/nodes/relation.h b/src/include/nodes/relation.h index 55850cef5e..98fb519111 100644 --- a/src/include/nodes/relation.h +++ b/src/include/nodes/relation.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: relation.h,v 1.40 2000/01/09 00:26:44 tgl Exp $ + * $Id: relation.h,v 1.41 2000/01/22 23:50:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -109,6 +109,7 @@ typedef struct RelOptInfo * indexkeys - List of base-relation attribute numbers that are index keys * ordering - List of PG_OPERATOR OIDs which order the indexscan result * relam - the OID of the pg_am of the index + * amcostestimate - OID of the relam's cost estimator * indproc - OID of the function if a functional index, else 0 * indpred - index predicate if a partial index, else NULL * @@ -132,6 +133,8 @@ typedef struct IndexOptInfo Oid *ordering; /* OIDs of sort operators for each key */ Oid relam; /* OID of the access method (in pg_am) */ + RegProcedure amcostestimate; /* OID of the access method's cost fcn */ + Oid indproc; /* if a functional index */ List *indpred; /* if a partial index */ } IndexOptInfo; diff --git a/src/include/optimizer/cost.h b/src/include/optimizer/cost.h index c654b6953e..9c16fc8fea 100644 --- a/src/include/optimizer/cost.h +++ b/src/include/optimizer/cost.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: cost.h,v 1.25 2000/01/09 00:26:46 tgl Exp $ + * $Id: cost.h,v 1.26 2000/01/22 23:50:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -20,23 +20,31 @@ #define PERBYTE_CPU 0 #define PERCALL_CPU 0 #define OUTIN_RATIO 100 +/* defaults for costsize.c's Cost parameters */ +/* NB: cost-estimation code should use the variables, not the constants! */ +#define CPU_PAGE_WEIGHT 0.033 +#define CPU_INDEX_PAGE_WEIGHT 0.017 + /* * prototypes for costsize.c * routines to compute costs and sizes */ -extern bool _enable_seqscan_; -extern bool _enable_indexscan_; -extern bool _enable_sort_; -extern bool _enable_nestloop_; -extern bool _enable_mergejoin_; -extern bool _enable_hashjoin_; -extern bool _enable_tidscan_; + +extern Cost cpu_page_weight; +extern Cost cpu_index_page_weight; +extern Cost disable_cost; +extern bool enable_seqscan; +extern bool enable_indexscan; +extern bool enable_tidscan; +extern bool enable_sort; +extern bool enable_nestloop; +extern bool enable_mergejoin; +extern bool enable_hashjoin; extern Cost cost_seqscan(RelOptInfo *baserel); -extern Cost cost_index(RelOptInfo *baserel, IndexOptInfo *index, - long expected_indexpages, Selectivity selec, - bool is_injoin); +extern Cost cost_index(Query *root, RelOptInfo *baserel, IndexOptInfo *index, + List *indexQuals, bool is_injoin); extern Cost cost_tidscan(RelOptInfo *baserel, List *tideval); extern Cost cost_sort(List *pathkeys, double tuples, int width); extern Cost cost_nestloop(Path *outer_path, Path *inner_path, diff --git a/src/include/optimizer/internal.h b/src/include/optimizer/internal.h index 14051ca81a..e89b244a39 100644 --- a/src/include/optimizer/internal.h +++ b/src/include/optimizer/internal.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: internal.h,v 1.24 2000/01/11 03:59:31 tgl Exp $ + * $Id: internal.h,v 1.25 2000/01/22 23:50:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -25,14 +25,6 @@ */ -/* - * System-dependent tuning constants - * - */ -#define _CPU_PAGE_WEIGHT_ 0.033 /* CPU-heap-to-page cost weighting factor */ -#define _CPU_INDEX_PAGE_WEIGHT_ 0.017 /* CPU-index-to-page cost - * weighting factor */ - /* * Size estimates * @@ -60,7 +52,4 @@ /* used to be -1 */ #define _NONAME_RELATION_ID_ InvalidOid -/* GEQO switch according to number of relations in a query */ -#define GEQO_RELS 11 - #endif /* INTERNAL_H */ diff --git a/src/include/optimizer/paths.h b/src/include/optimizer/paths.h index a3f6bad36b..1556941c4b 100644 --- a/src/include/optimizer/paths.h +++ b/src/include/optimizer/paths.h @@ -7,7 +7,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: paths.h,v 1.37 2000/01/09 00:26:47 tgl Exp $ + * $Id: paths.h,v 1.38 2000/01/22 23:50:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,9 +16,16 @@ #include "nodes/relation.h" +/* default GEQO threshold (default value for geqo_rels) */ +#define GEQO_RELS 11 + + /* * allpaths.c */ +extern bool enable_geqo; +extern int geqo_rels; + extern RelOptInfo *make_one_rel(Query *root, List *rels); /* diff --git a/src/include/optimizer/plancat.h b/src/include/optimizer/plancat.h index 307b51c3f4..024cfd6999 100644 --- a/src/include/optimizer/plancat.h +++ b/src/include/optimizer/plancat.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: plancat.h,v 1.15 2000/01/09 00:26:47 tgl Exp $ + * $Id: plancat.h,v 1.16 2000/01/22 23:50:27 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -30,10 +30,6 @@ extern Selectivity restriction_selectivity(Oid functionObjectId, Datum constValue, int constFlag); -extern void index_selectivity(Query *root, RelOptInfo *rel, - IndexOptInfo *index, List *indexquals, - long *idxPages, Selectivity *idxSelec); - extern Selectivity join_selectivity(Oid functionObjectId, Oid operatorObjectId, Oid relationObjectId1, AttrNumber attributeNumber1, Oid relationObjectId2, AttrNumber attributeNumber2); diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index 1be8ee5495..ae6e3daf62 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -6,7 +6,7 @@ * * Copyright (c) 1994, Regents of the University of California * - * $Id: builtins.h,v 1.96 2000/01/22 14:20:55 petere Exp $ + * $Id: builtins.h,v 1.97 2000/01/22 23:50:27 tgl Exp $ * * NOTES * This should normally only be included by fmgr.h. @@ -22,6 +22,8 @@ #ifndef BUILTINS_H #define BUILTINS_H +#include "access/heapam.h" /* for HeapTuple */ +#include "nodes/relation.h" /* for amcostestimate parameters */ #include "storage/itemptr.h" #include "utils/array.h" #include "utils/datetime.h" @@ -30,7 +32,6 @@ #include "utils/int8.h" #include "utils/nabstime.h" #include "utils/numeric.h" -#include "access/heapam.h" /* for HeapTuple */ /* * Defined in adt/ @@ -394,14 +395,23 @@ extern float64 eqjoinsel(Oid opid, Oid relid1, AttrNumber attno1, Oid relid2, At extern float64 neqjoinsel(Oid opid, Oid relid1, AttrNumber attno1, Oid relid2, AttrNumber attno2); extern float64 intltjoinsel(Oid opid, Oid relid1, AttrNumber attno1, Oid relid2, AttrNumber attno2); extern float64 intgtjoinsel(Oid opid, Oid relid1, AttrNumber attno1, Oid relid2, AttrNumber attno2); -extern float64 btreesel(Oid operatorOid, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid); -extern float64 btreenpage(Oid operatorOid, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid); -extern float64 hashsel(Oid operatorOid, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid); -extern float64 hashnpage(Oid operatorOid, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid); -extern float64 rtsel(Oid operatorOid, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid); -extern float64 rtnpage(Oid operatorOid, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid); -extern float64 gistsel(Oid operatorObjectId, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid); -extern float64 gistnpage(Oid operatorObjectId, Oid indrelid, AttrNumber attributeNumber, char *constValue, int32 constFlag, int32 nIndexKeys, Oid indexrelid); + +extern void btcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, + Selectivity *indexSelectivity); +extern void rtcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, + Selectivity *indexSelectivity); +extern void hashcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, + Selectivity *indexSelectivity); +extern void gistcostestimate(Query *root, RelOptInfo *rel, + IndexOptInfo *index, List *indexQuals, + Cost *indexAccessCost, + Selectivity *indexSelectivity); /* tid.c */ extern ItemPointer tidin(const char *str); diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql index 9964f5c1e1..e378171fd8 100644 --- a/src/test/regress/sql/opr_sanity.sql +++ b/src/test/regress/sql/opr_sanity.sql @@ -23,6 +23,8 @@ -- **************** pg_proc **************** -- Look for illegal values in pg_proc fields. +-- NOTE: currently there are a few pg_proc entries that have prorettype = 0. +-- Someday that ought to be cleaned up. SELECT p1.oid, p1.proname FROM pg_proc as p1 @@ -30,6 +32,7 @@ WHERE (p1.prolang = 0 OR p1.prorettype = 0 OR p1.pronargs < 0 OR p1.pronargs > 9) AND p1.proname !~ '^pl[^_]+_call_handler$' AND p1.proname !~ '^RI_FKey_' + AND p1.proname !~ 'costestimate$' AND p1.proname != 'update_pg_pwd'; -- Look for conflicting proc definitions (same names and input datatypes). @@ -416,7 +419,7 @@ WHERE p1.aggfinalfn = p2.oid AND SELECT p1.oid FROM pg_amop as p1 WHERE p1.amopid = 0 OR p1.amopclaid = 0 OR p1.amopopr = 0 OR - p1.amopstrategy <= 0 OR p1.amopselect = 0 OR p1.amopnpages = 0; + p1.amopstrategy <= 0; -- Look for duplicate pg_amop entries @@ -459,36 +462,6 @@ WHERE p1.amopopr = p2.oid AND p1.amopclaid = p3.oid AND p3.opcdeftype != 0 AND (p3.opcdeftype != p2.oprleft OR p3.opcdeftype != p2.oprright); --- Check that amopselect points to a proc with the right signature --- to be an access-method selectivity estimator. --- The proc signature we want is: --- float8 proc(oid, oid, int2, , int4, int4, oid) - -SELECT p1.oid, p2.oid, p2.proname -FROM pg_amop AS p1, pg_proc AS p2 -WHERE p1.amopselect = p2.oid AND - (p2.prorettype != 701 OR p2.proretset OR - p2.pronargs != 7 OR - p2.proargtypes[0] != 26 OR p2.proargtypes[1] != 26 OR - p2.proargtypes[2] != 21 OR p2.proargtypes[3] != 0 OR - p2.proargtypes[4] != 23 OR p2.proargtypes[5] != 23 OR - p2.proargtypes[6] != 26); - --- Check that amopnpages points to a proc with the right signature --- to be an access-method page-count estimator. --- The proc signature we want is: --- float8 proc(oid, oid, int2, , int4, int4, oid) - -SELECT p1.oid, p2.oid, p2.proname -FROM pg_amop AS p1, pg_proc AS p2 -WHERE p1.amopnpages = p2.oid AND - (p2.prorettype != 701 OR p2.proretset OR - p2.pronargs != 7 OR - p2.proargtypes[0] != 26 OR p2.proargtypes[1] != 26 OR - p2.proargtypes[2] != 21 OR p2.proargtypes[3] != 0 OR - p2.proargtypes[4] != 23 OR p2.proargtypes[5] != 23 OR - p2.proargtypes[6] != 26); - -- **************** pg_amproc **************** -- Look for illegal values in pg_amproc fields diff --git a/src/tutorial/complex.source b/src/tutorial/complex.source index bae3192198..847ec1a218 100644 --- a/src/tutorial/complex.source +++ b/src/tutorial/complex.source @@ -7,7 +7,7 @@ -- -- Copyright (c) 1994, Regents of the University of California -- --- $Id: complex.source,v 1.4 1998/03/01 04:52:59 scrappy Exp $ +-- $Id: complex.source,v 1.5 2000/01/22 23:50:30 tgl Exp $ -- --------------------------------------------------------------------------- @@ -184,42 +184,32 @@ WHERE o.oprleft = t.oid and o.oprright = t.oid -- make sure we have the right operators SELECT * from complex_ops_tmp; -INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, - amopselect, amopnpages) - SELECT am.oid, opcl.oid, c.opoid, 1, - 'btreesel'::regproc, 'btreenpage'::regproc +INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) + SELECT am.oid, opcl.oid, c.opoid, 1 FROM pg_am am, pg_opclass opcl, complex_ops_tmp c WHERE amname = 'btree' and opcname = 'complex_abs_ops' and c.oprname = '<'; -INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, - amopselect, amopnpages) - SELECT am.oid, opcl.oid, c.opoid, 2, - 'btreesel'::regproc, 'btreenpage'::regproc +INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) + SELECT am.oid, opcl.oid, c.opoid, 2 FROM pg_am am, pg_opclass opcl, complex_ops_tmp c WHERE amname = 'btree' and opcname = 'complex_abs_ops' and c.oprname = '<='; -INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, - amopselect, amopnpages) - SELECT am.oid, opcl.oid, c.opoid, 3, - 'btreesel'::regproc, 'btreenpage'::regproc +INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) + SELECT am.oid, opcl.oid, c.opoid, 3 FROM pg_am am, pg_opclass opcl, complex_ops_tmp c WHERE amname = 'btree' and opcname = 'complex_abs_ops' and c.oprname = '='; -INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, - amopselect, amopnpages) - SELECT am.oid, opcl.oid, c.opoid, 4, - 'btreesel'::regproc, 'btreenpage'::regproc +INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) + SELECT am.oid, opcl.oid, c.opoid, 4 FROM pg_am am, pg_opclass opcl, complex_ops_tmp c WHERE amname = 'btree' and opcname = 'complex_abs_ops' and c.oprname = '>='; -INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy, - amopselect, amopnpages) - SELECT am.oid, opcl.oid, c.opoid, 5, - 'btreesel'::regproc, 'btreenpage'::regproc +INSERT INTO pg_amop (amopid, amopclaid, amopopr, amopstrategy) + SELECT am.oid, opcl.oid, c.opoid, 5 FROM pg_am am, pg_opclass opcl, complex_ops_tmp c WHERE amname = 'btree' and opcname = 'complex_abs_ops' and c.oprname = '>';