Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
Postgres FD Implementation
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Abuhujair Javed
Postgres FD Implementation
Commits
c23bc6fb
Commit
c23bc6fb
authored
May 09, 2001
by
Tom Lane
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
First cut at making indexscan cost estimates depend on correlation
between index order and table order.
parent
e0203357
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
315 additions
and
86 deletions
+315
-86
doc/src/sgml/indexcost.sgml
doc/src/sgml/indexcost.sgml
+31
-5
src/backend/optimizer/path/costsize.c
src/backend/optimizer/path/costsize.c
+88
-33
src/backend/optimizer/util/var.c
src/backend/optimizer/util/var.c
+36
-21
src/backend/utils/adt/selfuncs.c
src/backend/utils/adt/selfuncs.c
+118
-19
src/backend/utils/cache/lsyscache.c
src/backend/utils/cache/lsyscache.c
+31
-1
src/include/catalog/pg_proc.h
src/include/catalog/pg_proc.h
+5
-5
src/include/optimizer/var.h
src/include/optimizer/var.h
+3
-1
src/include/utils/lsyscache.h
src/include/utils/lsyscache.h
+3
-1
No files found.
doc/src/sgml/indexcost.sgml
View file @
c23bc6fb
<!--
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/indexcost.sgml,v 2.
6 2000/12/22 21:51:57 petere
Exp $
$Header: /cvsroot/pgsql/doc/src/sgml/Attic/indexcost.sgml,v 2.
7 2001/05/09 23:13:34 tgl
Exp $
-->
<chapter id="indexcost">
...
...
@@ -57,7 +57,8 @@ amcostestimate (Query *root,
List *indexQuals,
Cost *indexStartupCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity);
Selectivity *indexSelectivity,
double *indexCorrelation);
</programlisting>
The first four parameters are inputs:
...
...
@@ -103,7 +104,7 @@ amcostestimate (Query *root,
</para>
<para>
The last
three
parameters are pass-by-reference outputs:
The last
four
parameters are pass-by-reference outputs:
<variablelist>
<varlistentry>
...
...
@@ -132,6 +133,16 @@ amcostestimate (Query *root,
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>*indexCorrelation</term>
<listitem>
<para>
Set to correlation coefficient between index scan order and
underlying table's order
</para>
</listitem>
</varlistentry>
</variablelist>
</para>
...
...
@@ -172,6 +183,13 @@ amcostestimate (Query *root,
tuples that actually pass the given qual conditions.
</para>
<para>
The indexCorrelation should be set to the correlation (ranging between
-1.0 and 1.0) between the index order and the table order. This is used
to adjust the estimate for the cost of fetching tuples from the main
table.
</para>
<procedure>
<title>Cost Estimation</title>
<para>
...
...
@@ -224,6 +242,14 @@ amcostestimate (Query *root,
</programlisting>
</para>
</step>
<step>
<para>
Estimate the index correlation. For a simple ordered index on a single
field, this can be retrieved from pg_statistic. If the correlation
is not known, the conservative estimate is zero (no correlation).
</para>
</step>
</procedure>
<para>
...
...
@@ -237,8 +263,8 @@ amcostestimate (Query *root,
<programlisting>
prorettype = 0
pronargs =
7
proargtypes = 0 0 0 0 0 0 0
pronargs =
8
proargtypes = 0 0 0 0 0 0 0
0
</programlisting>
We use zero ("opaque") for all the arguments since none of them have types
...
...
src/backend/optimizer/path/costsize.c
View file @
c23bc6fb
...
...
@@ -31,17 +31,18 @@
* result by interpolating between startup_cost and total_cost. In detail:
* actual_cost = startup_cost +
* (total_cost - startup_cost) * tuples_to_fetch / path->parent->rows;
* Note that a relation's rows count (and, by extension, a Plan's plan_rows)
* are set without regard to any LIMIT, so that this equation works properly.
* (Also, these routines guarantee not to set the rows count to zero, so there
* will be no zero divide.) The LIMIT is applied as a separate Plan node.
* Note that a base relation's rows count (and, by extension, plan_rows for
* plan nodes below the LIMIT node) are set without regard to any LIMIT, so
* that this equation works properly. (Also, these routines guarantee not to
* set the rows count to zero, so there will be no zero divide.) The LIMIT is
* applied as a top-level plan node.
*
*
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.7
2 2001/05/09 00:35:09
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/path/costsize.c,v 1.7
3 2001/05/09 23:13:34
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -205,12 +206,18 @@ cost_index(Path *path, Query *root,
{
Cost
startup_cost
=
0
;
Cost
run_cost
=
0
;
Cost
cpu_per_tuple
;
Cost
indexStartupCost
;
Cost
indexTotalCost
;
Selectivity
indexSelectivity
;
double
indexCorrelation
,
csquared
;
Cost
min_IO_cost
,
max_IO_cost
;
Cost
cpu_per_tuple
;
double
tuples_fetched
;
double
pages_fetched
;
double
T
,
b
;
/* Should only be applied to base relations */
Assert
(
IsA
(
baserel
,
RelOptInfo
)
&&
IsA
(
index
,
IndexOptInfo
));
...
...
@@ -224,38 +231,52 @@ cost_index(Path *path, Query *root,
* 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).
* retrieve)
and its correlation to the main-table tuple order
.
*/
OidFunctionCall
7
(
index
->
amcostestimate
,
OidFunctionCall
8
(
index
->
amcostestimate
,
PointerGetDatum
(
root
),
PointerGetDatum
(
baserel
),
PointerGetDatum
(
index
),
PointerGetDatum
(
indexQuals
),
PointerGetDatum
(
&
indexStartupCost
),
PointerGetDatum
(
&
indexTotalCost
),
PointerGetDatum
(
&
indexSelectivity
));
PointerGetDatum
(
&
indexSelectivity
),
PointerGetDatum
(
&
indexCorrelation
));
/* all costs for touching index itself included here */
startup_cost
+=
indexStartupCost
;
run_cost
+=
indexTotalCost
-
indexStartupCost
;
/*
/*
----------
* Estimate number of main-table tuples and pages fetched.
*
* If the number of tuples is much smaller than the number of pages in
* the relation, each tuple will cost a separate nonsequential fetch.
* If it is comparable or larger, then probably we will be able to
* avoid some fetches. We use a growth rate of log(#tuples/#pages +
* 1) --- probably totally bogus, but intuitively it gives the right
* shape of curve at least.
* When the index ordering is uncorrelated with the table ordering,
* we use an approximation proposed by Mackert and Lohman, "Index Scans
* Using a Finite LRU Buffer: A Validated I/O Model", ACM Transactions
* on Database Systems, Vol. 14, No. 3, September 1989, Pages 401-424.
* The Mackert and Lohman approximation is that the number of pages
* fetched is
* PF =
* min(2TNs/(2T+Ns), T) when T <= b
* 2TNs/(2T+Ns) when T > b and Ns <= 2Tb/(2T-b)
* b + (Ns - 2Tb/(2T-b))*(T-b)/T when T > b and Ns > 2Tb/(2T-b)
* where
* T = # pages in table
* N = # tuples in table
* s = selectivity = fraction of table to be scanned
* b = # buffer pages available (we include kernel space here)
*
* 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 have no way to know whether the relation has been
* clustered, nor how much it's been modified since the last
* clustering, so we ignore this effect. Would be nice to do better
* someday.
* When the index ordering is exactly correlated with the table ordering
* (just after a CLUSTER, for example), the number of pages fetched should
* be just sT. What's more, these will be sequential fetches, not the
* random fetches that occur in the uncorrelated case. So, depending on
* the extent of correlation, we should estimate the actual I/O cost
* somewhere between s * T * 1.0 and PF * random_cost. We currently
* interpolate linearly between these two endpoints based on the
* correlation squared (XXX is that appropriate?).
*
* In any case the number of tuples fetched is Ns.
*----------
*/
tuples_fetched
=
indexSelectivity
*
baserel
->
tuples
;
...
...
@@ -263,24 +284,56 @@ cost_index(Path *path, Query *root,
if
(
tuples_fetched
<
1
.
0
)
tuples_fetched
=
1
.
0
;
if
(
baserel
->
pages
>
0
)
pages_fetched
=
ceil
(
baserel
->
pages
*
log
(
tuples_fetched
/
baserel
->
pages
+
1
.
0
));
/* This part is the Mackert and Lohman formula */
T
=
(
baserel
->
pages
>
1
)
?
(
double
)
baserel
->
pages
:
1
.
0
;
b
=
(
effective_cache_size
>
1
)
?
effective_cache_size
:
1
.
0
;
if
(
T
<=
b
)
{
pages_fetched
=
(
2
.
0
*
T
*
tuples_fetched
)
/
(
2
.
0
*
T
+
tuples_fetched
);
if
(
pages_fetched
>
T
)
pages_fetched
=
T
;
}
else
pages_fetched
=
tuples_fetched
;
{
double
lim
;
lim
=
(
2
.
0
*
T
*
b
)
/
(
2
.
0
*
T
-
b
);
if
(
tuples_fetched
<=
lim
)
{
pages_fetched
=
(
2
.
0
*
T
*
tuples_fetched
)
/
(
2
.
0
*
T
+
tuples_fetched
);
}
else
{
pages_fetched
=
b
+
(
tuples_fetched
-
lim
)
*
(
T
-
b
)
/
T
;
}
}
/*
* Now estimate one nonsequential access per page fetched, plus
* appropriate CPU costs per tuple.
* min_IO_cost corresponds to the perfectly correlated case (csquared=1),
* max_IO_cost to the perfectly uncorrelated case (csquared=0). Note
* that we just charge random_page_cost per page in the uncorrelated
* case, rather than using cost_nonsequential_access, since we've already
* accounted for caching effects by using the Mackert model.
*/
min_IO_cost
=
ceil
(
indexSelectivity
*
T
);
max_IO_cost
=
pages_fetched
*
random_page_cost
;
/* disk costs for main table */
run_cost
+=
pages_fetched
*
cost_nonsequential_access
(
baserel
->
pages
);
/*
* Now interpolate based on estimated index order correlation
* to get total disk I/O cost for main table accesses.
*/
csquared
=
indexCorrelation
*
indexCorrelation
;
/* CPU costs */
cpu_per_tuple
=
cpu_tuple_cost
+
baserel
->
baserestrictcost
;
run_cost
+=
max_IO_cost
+
csquared
*
(
min_IO_cost
-
max_IO_cost
);
/*
* Estimate CPU costs per tuple.
*
* Normally the indexquals will be removed from the list of
* restriction clauses that we have to evaluate as qpquals, so we
* should subtract their costs from baserestrictcost. For a lossy
...
...
@@ -290,6 +343,8 @@ cost_index(Path *path, Query *root,
* Rather than work out exactly how much to subtract, we don't
* subtract anything in that case either.
*/
cpu_per_tuple
=
cpu_tuple_cost
+
baserel
->
baserestrictcost
;
if
(
!
index
->
lossy
&&
!
is_injoin
)
cpu_per_tuple
-=
cost_qual_eval
(
indexQuals
);
...
...
src/backend/optimizer/util/var.c
View file @
c23bc6fb
...
...
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.3
1 2001/04/18 20:42:5
5 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/optimizer/util/var.c,v 1.3
2 2001/05/09 23:13:3
5 tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -28,8 +28,9 @@ typedef struct
typedef
struct
{
int
varno
;
int
varattno
;
int
sublevels_up
;
}
contain_
whole_tuple_var
_context
;
}
contain_
var_reference
_context
;
typedef
struct
{
...
...
@@ -39,8 +40,8 @@ typedef struct
static
bool
pull_varnos_walker
(
Node
*
node
,
pull_varnos_context
*
context
);
static
bool
contain_
whole_tuple_var
_walker
(
Node
*
node
,
contain_
whole_tuple_var
_context
*
context
);
static
bool
contain_
var_reference
_walker
(
Node
*
node
,
contain_
var_reference
_context
*
context
);
static
bool
contain_var_clause_walker
(
Node
*
node
,
void
*
context
);
static
bool
pull_var_clause_walker
(
Node
*
node
,
pull_var_clause_context
*
context
);
...
...
@@ -129,10 +130,10 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
/*
* contain_
whole_tuple_var
* contain_
var_reference
*
* Detect whether a parsetree contains any references to
the whole
*
tuple of a given rtable entry (ie, a Var with varattno = 0)
.
* Detect whether a parsetree contains any references to
a specified
*
attribute of a specified rtable entry
.
*
* NOTE: this is used on not-yet-planned expressions. It may therefore find
* bare SubLinks, and if so it needs to recurse into them to look for uplevel
...
...
@@ -140,11 +141,12 @@ pull_varnos_walker(Node *node, pull_varnos_context *context)
* SubPlan, we only need to look at the parameters passed to the subplan.
*/
bool
contain_
whole_tuple_var
(
Node
*
node
,
int
var
no
,
int
levelsup
)
contain_
var_reference
(
Node
*
node
,
int
varno
,
int
varatt
no
,
int
levelsup
)
{
contain_
whole_tuple_var
_context
context
;
contain_
var_reference
_context
context
;
context
.
varno
=
varno
;
context
.
varattno
=
varattno
;
context
.
sublevels_up
=
levelsup
;
/*
...
...
@@ -154,15 +156,15 @@ contain_whole_tuple_var(Node *node, int varno, int levelsup)
*/
if
(
node
&&
IsA
(
node
,
Query
))
return
query_tree_walker
((
Query
*
)
node
,
contain_
whole_tuple_var
_walker
,
contain_
var_reference
_walker
,
(
void
*
)
&
context
,
true
);
else
return
contain_
whole_tuple_var
_walker
(
node
,
&
context
);
return
contain_
var_reference
_walker
(
node
,
&
context
);
}
static
bool
contain_
whole_tuple_var
_walker
(
Node
*
node
,
contain_whole_tuple_var
_context
*
context
)
contain_
var_reference
_walker
(
Node
*
node
,
contain_var_reference
_context
*
context
)
{
if
(
node
==
NULL
)
return
false
;
...
...
@@ -171,8 +173,8 @@ contain_whole_tuple_var_walker(Node *node,
Var
*
var
=
(
Var
*
)
node
;
if
(
var
->
varno
==
context
->
varno
&&
var
->
var
levelsup
==
context
->
sublevels_up
&&
var
->
var
attno
==
InvalidAttrNumber
)
var
->
var
attno
==
context
->
varattno
&&
var
->
var
levelsup
==
context
->
sublevels_up
)
return
true
;
return
false
;
}
...
...
@@ -187,10 +189,10 @@ contain_whole_tuple_var_walker(Node *node,
*/
Expr
*
expr
=
(
Expr
*
)
node
;
if
(
contain_
whole_tuple_var
_walker
((
Node
*
)
((
SubPlan
*
)
expr
->
oper
)
->
sublink
->
oper
,
if
(
contain_
var_reference
_walker
((
Node
*
)
((
SubPlan
*
)
expr
->
oper
)
->
sublink
->
oper
,
context
))
return
true
;
if
(
contain_
whole_tuple_var
_walker
((
Node
*
)
expr
->
args
,
if
(
contain_
var_reference
_walker
((
Node
*
)
expr
->
args
,
context
))
return
true
;
return
false
;
...
...
@@ -202,16 +204,29 @@ contain_whole_tuple_var_walker(Node *node,
context
->
sublevels_up
++
;
result
=
query_tree_walker
((
Query
*
)
node
,
contain_
whole_tuple_var
_walker
,
contain_
var_reference
_walker
,
(
void
*
)
context
,
true
);
context
->
sublevels_up
--
;
return
result
;
}
return
expression_tree_walker
(
node
,
contain_
whole_tuple_var
_walker
,
return
expression_tree_walker
(
node
,
contain_
var_reference
_walker
,
(
void
*
)
context
);
}
/*
* contain_whole_tuple_var
*
* Detect whether a parsetree contains any references to the whole
* tuple of a given rtable entry (ie, a Var with varattno = 0).
*/
bool
contain_whole_tuple_var
(
Node
*
node
,
int
varno
,
int
levelsup
)
{
return
contain_var_reference
(
node
,
varno
,
InvalidAttrNumber
,
levelsup
);
}
/*
* contain_var_clause
* Recursively scan a clause to discover whether it contains any Var nodes
...
...
src/backend/utils/adt/selfuncs.c
View file @
c23bc6fb
...
...
@@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.8
8 2001/05/07 00:43:23
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.8
9 2001/05/09 23:13:35
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -39,6 +39,7 @@
#include "optimizer/cost.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/int8.h"
...
...
@@ -818,7 +819,6 @@ eqjoinsel(PG_FUNCTION_ARGS)
{
#ifdef NOT_USED
/* see neqjoinsel() before removing me! */
Oid
opid
=
PG_GETARG_OID
(
0
);
#endif
Oid
relid1
=
PG_GETARG_OID
(
1
);
AttrNumber
attno1
=
PG_GETARG_INT16
(
2
);
...
...
@@ -2230,16 +2230,14 @@ string_to_datum(const char *str, Oid datatype)
*-------------------------------------------------------------------------
*/
static
Datum
genericcostestimate
(
PG_FUNCTION_ARGS
)
static
void
genericcostestimate
(
Query
*
root
,
RelOptInfo
*
rel
,
IndexOptInfo
*
index
,
List
*
indexQuals
,
Cost
*
indexStartupCost
,
Cost
*
indexTotalCost
,
Selectivity
*
indexSelectivity
,
double
*
indexCorrelation
)
{
Query
*
root
=
(
Query
*
)
PG_GETARG_POINTER
(
0
);
RelOptInfo
*
rel
=
(
RelOptInfo
*
)
PG_GETARG_POINTER
(
1
);
IndexOptInfo
*
index
=
(
IndexOptInfo
*
)
PG_GETARG_POINTER
(
2
);
List
*
indexQuals
=
(
List
*
)
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
numIndexTuples
;
double
numIndexPages
;
...
...
@@ -2275,33 +2273,134 @@ genericcostestimate(PG_FUNCTION_ARGS)
*
indexTotalCost
=
numIndexPages
+
(
cpu_index_tuple_cost
+
cost_qual_eval
(
indexQuals
))
*
numIndexTuples
;
PG_RETURN_VOID
();
/*
* Generic assumption about index correlation: there isn't any.
*/
*
indexCorrelation
=
0
.
0
;
}
/*
* For first cut, just use generic function for all index types.
*/
Datum
btcostestimate
(
PG_FUNCTION_ARGS
)
{
return
genericcostestimate
(
fcinfo
);
Query
*
root
=
(
Query
*
)
PG_GETARG_POINTER
(
0
);
RelOptInfo
*
rel
=
(
RelOptInfo
*
)
PG_GETARG_POINTER
(
1
);
IndexOptInfo
*
index
=
(
IndexOptInfo
*
)
PG_GETARG_POINTER
(
2
);
List
*
indexQuals
=
(
List
*
)
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
,
rel
,
index
,
indexQuals
,
indexStartupCost
,
indexTotalCost
,
indexSelectivity
,
indexCorrelation
);
/*
* If it's a functional index, leave the default zero-correlation
* estimate in place. If not, and if we can get an estimate for
* the first variable's ordering correlation C from pg_statistic,
* estimate the index correlation as C / number-of-columns.
* (The idea here is that multiple columns dilute the importance
* of the first column's ordering, but don't negate it entirely.)
*/
if
(
index
->
indproc
==
InvalidOid
)
{
Oid
relid
;
HeapTuple
tuple
;
relid
=
getrelid
(
lfirsti
(
rel
->
relids
),
root
->
rtable
);
Assert
(
relid
!=
InvalidOid
);
tuple
=
SearchSysCache
(
STATRELATT
,
ObjectIdGetDatum
(
relid
),
Int16GetDatum
(
index
->
indexkeys
[
0
]),
0
,
0
);
if
(
HeapTupleIsValid
(
tuple
))
{
Oid
typid
;
int32
typmod
;
float4
*
numbers
;
int
nnumbers
;
get_atttypetypmod
(
relid
,
index
->
indexkeys
[
0
],
&
typid
,
&
typmod
);
if
(
get_attstatsslot
(
tuple
,
typid
,
typmod
,
STATISTIC_KIND_CORRELATION
,
index
->
ordering
[
0
],
NULL
,
NULL
,
&
numbers
,
&
nnumbers
))
{
double
varCorrelation
;
int
nKeys
;
Assert
(
nnumbers
==
1
);
varCorrelation
=
numbers
[
0
];
for
(
nKeys
=
1
;
index
->
indexkeys
[
nKeys
]
!=
0
;
nKeys
++
)
/*skip*/
;
*
indexCorrelation
=
varCorrelation
/
nKeys
;
free_attstatsslot
(
typid
,
NULL
,
0
,
numbers
,
nnumbers
);
}
ReleaseSysCache
(
tuple
);
}
}
PG_RETURN_VOID
();
}
Datum
rtcostestimate
(
PG_FUNCTION_ARGS
)
{
return
genericcostestimate
(
fcinfo
);
Query
*
root
=
(
Query
*
)
PG_GETARG_POINTER
(
0
);
RelOptInfo
*
rel
=
(
RelOptInfo
*
)
PG_GETARG_POINTER
(
1
);
IndexOptInfo
*
index
=
(
IndexOptInfo
*
)
PG_GETARG_POINTER
(
2
);
List
*
indexQuals
=
(
List
*
)
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
,
rel
,
index
,
indexQuals
,
indexStartupCost
,
indexTotalCost
,
indexSelectivity
,
indexCorrelation
);
PG_RETURN_VOID
();
}
Datum
hashcostestimate
(
PG_FUNCTION_ARGS
)
{
return
genericcostestimate
(
fcinfo
);
Query
*
root
=
(
Query
*
)
PG_GETARG_POINTER
(
0
);
RelOptInfo
*
rel
=
(
RelOptInfo
*
)
PG_GETARG_POINTER
(
1
);
IndexOptInfo
*
index
=
(
IndexOptInfo
*
)
PG_GETARG_POINTER
(
2
);
List
*
indexQuals
=
(
List
*
)
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
,
rel
,
index
,
indexQuals
,
indexStartupCost
,
indexTotalCost
,
indexSelectivity
,
indexCorrelation
);
PG_RETURN_VOID
();
}
Datum
gistcostestimate
(
PG_FUNCTION_ARGS
)
{
return
genericcostestimate
(
fcinfo
);
Query
*
root
=
(
Query
*
)
PG_GETARG_POINTER
(
0
);
RelOptInfo
*
rel
=
(
RelOptInfo
*
)
PG_GETARG_POINTER
(
1
);
IndexOptInfo
*
index
=
(
IndexOptInfo
*
)
PG_GETARG_POINTER
(
2
);
List
*
indexQuals
=
(
List
*
)
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
,
rel
,
index
,
indexQuals
,
indexStartupCost
,
indexTotalCost
,
indexSelectivity
,
indexCorrelation
);
PG_RETURN_VOID
();
}
src/backend/utils/cache/lsyscache.c
View file @
c23bc6fb
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.5
4 2001/05/09 00:35:09
tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/lsyscache.c,v 1.5
5 2001/05/09 23:13:35
tgl Exp $
*
* NOTES
* Eventually, the index information should go through here, too.
...
...
@@ -185,6 +185,36 @@ get_atttypmod(Oid relid, AttrNumber attnum)
return
-
1
;
}
/*
* get_atttypetypmod
*
* A two-fer: given the relation id and the attribute number,
* fetch both type OID and atttypmod in a single cache lookup.
*
* Unlike the otherwise-similar get_atttype/get_atttypmod, this routine
* raises an error if it can't obtain the information.
*/
void
get_atttypetypmod
(
Oid
relid
,
AttrNumber
attnum
,
Oid
*
typid
,
int32
*
typmod
)
{
HeapTuple
tp
;
Form_pg_attribute
att_tup
;
tp
=
SearchSysCache
(
ATTNUM
,
ObjectIdGetDatum
(
relid
),
Int16GetDatum
(
attnum
),
0
,
0
);
if
(
!
HeapTupleIsValid
(
tp
))
elog
(
ERROR
,
"cache lookup failed for relation %u attribute %d"
,
relid
,
attnum
);
att_tup
=
(
Form_pg_attribute
)
GETSTRUCT
(
tp
);
*
typid
=
att_tup
->
atttypid
;
*
typmod
=
att_tup
->
atttypmod
;
ReleaseSysCache
(
tp
);
}
/* ---------- INDEX CACHE ---------- */
/* watch this space...
...
...
src/include/catalog/pg_proc.h
View file @
c23bc6fb
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: pg_proc.h,v 1.18
4 2001/03/22 04:00:39 momjian
Exp $
* $Id: pg_proc.h,v 1.18
5 2001/05/09 23:13:35 tgl
Exp $
*
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
...
...
@@ -210,9 +210,9 @@ DESCR("not equal");
DATA
(
insert
OID
=
89
(
version
PGUID
12
f
t
f
t
0
f
25
""
100
0
0
100
pgsql_version
-
));
DESCR
(
"PostgreSQL version string"
);
DATA
(
insert
OID
=
1265
(
rtcostestimate
PGUID
12
f
t
f
t
7
f
0
"
0 0 0 0 0 0 0"
100
0
0
100
rtcostestimate
-
));
DATA
(
insert
OID
=
1265
(
rtcostestimate
PGUID
12
f
t
f
t
8
f
0
"0
0 0 0 0 0 0 0"
100
0
0
100
rtcostestimate
-
));
DESCR
(
"r-tree cost estimator"
);
DATA
(
insert
OID
=
1268
(
btcostestimate
PGUID
12
f
t
f
t
7
f
0
"
0 0 0 0 0 0 0"
100
0
0
100
btcostestimate
-
));
DATA
(
insert
OID
=
1268
(
btcostestimate
PGUID
12
f
t
f
t
8
f
0
"0
0 0 0 0 0 0 0"
100
0
0
100
btcostestimate
-
));
DESCR
(
"btree cost estimator"
);
/* OIDS 100 - 199 */
...
...
@@ -789,7 +789,7 @@ DESCR("convert name to char()");
DATA
(
insert
OID
=
409
(
name
PGUID
12
f
t
t
t
1
f
19
"1042"
100
0
0
100
bpchar_name
-
));
DESCR
(
"convert char() to name"
);
DATA
(
insert
OID
=
438
(
hashcostestimate
PGUID
12
f
t
f
t
7
f
0
"
0 0 0 0 0 0 0"
100
0
0
100
hashcostestimate
-
));
DATA
(
insert
OID
=
438
(
hashcostestimate
PGUID
12
f
t
f
t
8
f
0
"0
0 0 0 0 0 0 0"
100
0
0
100
hashcostestimate
-
));
DESCR
(
"hash index cost estimator"
);
DATA
(
insert
OID
=
440
(
hashgettuple
PGUID
12
f
t
f
t
2
f
23
"0 0"
100
0
0
100
hashgettuple
-
));
...
...
@@ -1014,7 +1014,7 @@ DESCR("larger of two");
DATA
(
insert
OID
=
771
(
int2smaller
PGUID
12
f
t
t
t
2
f
21
"21 21"
100
0
0
100
int2smaller
-
));
DESCR
(
"smaller of two"
);
DATA
(
insert
OID
=
772
(
gistcostestimate
PGUID
12
f
t
f
t
7
f
0
"
0 0 0 0 0 0 0"
100
0
0
100
gistcostestimate
-
));
DATA
(
insert
OID
=
772
(
gistcostestimate
PGUID
12
f
t
f
t
8
f
0
"0
0 0 0 0 0 0 0"
100
0
0
100
gistcostestimate
-
));
DESCR
(
"gist cost estimator"
);
DATA
(
insert
OID
=
774
(
gistgettuple
PGUID
12
f
t
f
t
2
f
23
"0 0"
100
0
0
100
gistgettuple
-
));
DESCR
(
"gist(internal)"
);
...
...
src/include/optimizer/var.h
View file @
c23bc6fb
...
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: var.h,v 1.1
3 2001/04/18 20:42:55
tgl Exp $
* $Id: var.h,v 1.1
4 2001/05/09 23:13:36
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -17,6 +17,8 @@
#include "nodes/primnodes.h"
extern
List
*
pull_varnos
(
Node
*
node
);
extern
bool
contain_var_reference
(
Node
*
node
,
int
varno
,
int
varattno
,
int
levelsup
);
extern
bool
contain_whole_tuple_var
(
Node
*
node
,
int
varno
,
int
levelsup
);
extern
bool
contain_var_clause
(
Node
*
node
);
extern
List
*
pull_var_clause
(
Node
*
node
,
bool
includeUpperVars
);
...
...
src/include/utils/lsyscache.h
View file @
c23bc6fb
...
...
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: lsyscache.h,v 1.3
2 2001/05/09 00:35:09
tgl Exp $
* $Id: lsyscache.h,v 1.3
3 2001/05/09 23:13:37
tgl Exp $
*
*-------------------------------------------------------------------------
*/
...
...
@@ -21,6 +21,8 @@ extern AttrNumber get_attnum(Oid relid, char *attname);
extern
Oid
get_atttype
(
Oid
relid
,
AttrNumber
attnum
);
extern
bool
get_attisset
(
Oid
relid
,
char
*
attname
);
extern
int32
get_atttypmod
(
Oid
relid
,
AttrNumber
attnum
);
extern
void
get_atttypetypmod
(
Oid
relid
,
AttrNumber
attnum
,
Oid
*
typid
,
int32
*
typmod
);
extern
RegProcedure
get_opcode
(
Oid
opno
);
extern
char
*
get_opname
(
Oid
opno
);
extern
bool
op_mergejoinable
(
Oid
opno
,
Oid
ltype
,
Oid
rtype
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment