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">
<chapter id="indexcost">
...
@@ -57,7 +57,8 @@ amcostestimate (Query *root,
...
@@ -57,7 +57,8 @@ amcostestimate (Query *root,
List *indexQuals,
List *indexQuals,
Cost *indexStartupCost,
Cost *indexStartupCost,
Cost *indexTotalCost,
Cost *indexTotalCost,
Selectivity *indexSelectivity);
Selectivity *indexSelectivity,
double *indexCorrelation);
</programlisting>
</programlisting>
The first four parameters are inputs:
The first four parameters are inputs:
...
@@ -103,7 +104,7 @@ amcostestimate (Query *root,
...
@@ -103,7 +104,7 @@ amcostestimate (Query *root,
</para>
</para>
<para>
<para>
The last
three
parameters are pass-by-reference outputs:
The last
four
parameters are pass-by-reference outputs:
<variablelist>
<variablelist>
<varlistentry>
<varlistentry>
...
@@ -132,6 +133,16 @@ amcostestimate (Query *root,
...
@@ -132,6 +133,16 @@ amcostestimate (Query *root,
</para>
</para>
</listitem>
</listitem>
</varlistentry>
</varlistentry>
<varlistentry>
<term>*indexCorrelation</term>
<listitem>
<para>
Set to correlation coefficient between index scan order and
underlying table's order
</para>
</listitem>
</varlistentry>
</variablelist>
</variablelist>
</para>
</para>
...
@@ -172,6 +183,13 @@ amcostestimate (Query *root,
...
@@ -172,6 +183,13 @@ amcostestimate (Query *root,
tuples that actually pass the given qual conditions.
tuples that actually pass the given qual conditions.
</para>
</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>
<procedure>
<title>Cost Estimation</title>
<title>Cost Estimation</title>
<para>
<para>
...
@@ -224,6 +242,14 @@ amcostestimate (Query *root,
...
@@ -224,6 +242,14 @@ amcostestimate (Query *root,
</programlisting>
</programlisting>
</para>
</para>
</step>
</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>
</procedure>
<para>
<para>
...
@@ -237,8 +263,8 @@ amcostestimate (Query *root,
...
@@ -237,8 +263,8 @@ amcostestimate (Query *root,
<programlisting>
<programlisting>
prorettype = 0
prorettype = 0
pronargs =
7
pronargs =
8
proargtypes = 0 0 0 0 0 0 0
proargtypes = 0 0 0 0 0 0 0
0
</programlisting>
</programlisting>
We use zero ("opaque") for all the arguments since none of them have types
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 @@
...
@@ -31,17 +31,18 @@
* result by interpolating between startup_cost and total_cost. In detail:
* result by interpolating between startup_cost and total_cost. In detail:
* actual_cost = startup_cost +
* actual_cost = startup_cost +
* (total_cost - startup_cost) * tuples_to_fetch / path->parent->rows;
* (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)
* Note that a base relation's rows count (and, by extension, plan_rows for
* are set without regard to any LIMIT, so that this equation works properly.
* plan nodes below the LIMIT node) are set without regard to any LIMIT, so
* (Also, these routines guarantee not to set the rows count to zero, so there
* that this equation works properly. (Also, these routines guarantee not to
* will be no zero divide.) The LIMIT is applied as a separate Plan node.
* 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) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* 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,
...
@@ -205,12 +206,18 @@ cost_index(Path *path, Query *root,
{
{
Cost
startup_cost
=
0
;
Cost
startup_cost
=
0
;
Cost
run_cost
=
0
;
Cost
run_cost
=
0
;
Cost
cpu_per_tuple
;
Cost
indexStartupCost
;
Cost
indexStartupCost
;
Cost
indexTotalCost
;
Cost
indexTotalCost
;
Selectivity
indexSelectivity
;
Selectivity
indexSelectivity
;
double
indexCorrelation
,
csquared
;
Cost
min_IO_cost
,
max_IO_cost
;
Cost
cpu_per_tuple
;
double
tuples_fetched
;
double
tuples_fetched
;
double
pages_fetched
;
double
pages_fetched
;
double
T
,
b
;
/* Should only be applied to base relations */
/* Should only be applied to base relations */
Assert
(
IsA
(
baserel
,
RelOptInfo
)
&&
IsA
(
index
,
IndexOptInfo
));
Assert
(
IsA
(
baserel
,
RelOptInfo
)
&&
IsA
(
index
,
IndexOptInfo
));
...
@@ -224,38 +231,52 @@ cost_index(Path *path, Query *root,
...
@@ -224,38 +231,52 @@ cost_index(Path *path, Query *root,
* Call index-access-method-specific code to estimate the processing
* Call index-access-method-specific code to estimate the processing
* cost for scanning the index, as well as the selectivity of the
* cost for scanning the index, as well as the selectivity of the
* index (ie, the fraction of main-table tuples we will have to
* 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
(
root
),
PointerGetDatum
(
baserel
),
PointerGetDatum
(
baserel
),
PointerGetDatum
(
index
),
PointerGetDatum
(
index
),
PointerGetDatum
(
indexQuals
),
PointerGetDatum
(
indexQuals
),
PointerGetDatum
(
&
indexStartupCost
),
PointerGetDatum
(
&
indexStartupCost
),
PointerGetDatum
(
&
indexTotalCost
),
PointerGetDatum
(
&
indexTotalCost
),
PointerGetDatum
(
&
indexSelectivity
));
PointerGetDatum
(
&
indexSelectivity
),
PointerGetDatum
(
&
indexCorrelation
));
/* all costs for touching index itself included here */
/* all costs for touching index itself included here */
startup_cost
+=
indexStartupCost
;
startup_cost
+=
indexStartupCost
;
run_cost
+=
indexTotalCost
-
indexStartupCost
;
run_cost
+=
indexTotalCost
-
indexStartupCost
;
/*
/*
----------
* Estimate number of main-table tuples and pages fetched.
* Estimate number of main-table tuples and pages fetched.
*
*
* If the number of tuples is much smaller than the number of pages in
* When the index ordering is uncorrelated with the table ordering,
* the relation, each tuple will cost a separate nonsequential fetch.
* we use an approximation proposed by Mackert and Lohman, "Index Scans
* If it is comparable or larger, then probably we will be able to
* Using a Finite LRU Buffer: A Validated I/O Model", ACM Transactions
* avoid some fetches. We use a growth rate of log(#tuples/#pages +
* on Database Systems, Vol. 14, No. 3, September 1989, Pages 401-424.
* 1) --- probably totally bogus, but intuitively it gives the right
* The Mackert and Lohman approximation is that the number of pages
* shape of curve at least.
* 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,
* When the index ordering is exactly correlated with the table ordering
* then in fact the target tuples will be highly nonuniformly
* (just after a CLUSTER, for example), the number of pages fetched should
* distributed, and we will be seriously overestimating the scan cost!
* be just sT. What's more, these will be sequential fetches, not the
* Currently we have no way to know whether the relation has been
* random fetches that occur in the uncorrelated case. So, depending on
* clustered, nor how much it's been modified since the last
* the extent of correlation, we should estimate the actual I/O cost
* clustering, so we ignore this effect. Would be nice to do better
* somewhere between s * T * 1.0 and PF * random_cost. We currently
* someday.
* 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
;
tuples_fetched
=
indexSelectivity
*
baserel
->
tuples
;
...
@@ -263,24 +284,56 @@ cost_index(Path *path, Query *root,
...
@@ -263,24 +284,56 @@ cost_index(Path *path, Query *root,
if
(
tuples_fetched
<
1
.
0
)
if
(
tuples_fetched
<
1
.
0
)
tuples_fetched
=
1
.
0
;
tuples_fetched
=
1
.
0
;
if
(
baserel
->
pages
>
0
)
/* This part is the Mackert and Lohman formula */
pages_fetched
=
ceil
(
baserel
->
pages
*
log
(
tuples_fetched
/
baserel
->
pages
+
1
.
0
));
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
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
* min_IO_cost corresponds to the perfectly correlated case (csquared=1),
* appropriate CPU costs per tuple.
* 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 */
run_cost
+=
max_IO_cost
+
csquared
*
(
min_IO_cost
-
max_IO_cost
);
cpu_per_tuple
=
cpu_tuple_cost
+
baserel
->
baserestrictcost
;
/*
/*
* Estimate CPU costs per tuple.
*
* Normally the indexquals will be removed from the list of
* Normally the indexquals will be removed from the list of
* restriction clauses that we have to evaluate as qpquals, so we
* restriction clauses that we have to evaluate as qpquals, so we
* should subtract their costs from baserestrictcost. For a lossy
* should subtract their costs from baserestrictcost. For a lossy
...
@@ -290,6 +343,8 @@ cost_index(Path *path, Query *root,
...
@@ -290,6 +343,8 @@ cost_index(Path *path, Query *root,
* Rather than work out exactly how much to subtract, we don't
* Rather than work out exactly how much to subtract, we don't
* subtract anything in that case either.
* subtract anything in that case either.
*/
*/
cpu_per_tuple
=
cpu_tuple_cost
+
baserel
->
baserestrictcost
;
if
(
!
index
->
lossy
&&
!
is_injoin
)
if
(
!
index
->
lossy
&&
!
is_injoin
)
cpu_per_tuple
-=
cost_qual_eval
(
indexQuals
);
cpu_per_tuple
-=
cost_qual_eval
(
indexQuals
);
...
...
src/backend/optimizer/util/var.c
View file @
c23bc6fb
...
@@ -8,7 +8,7 @@
...
@@ -8,7 +8,7 @@
*
*
*
*
* IDENTIFICATION
* 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
...
@@ -28,8 +28,9 @@ typedef struct
typedef
struct
typedef
struct
{
{
int
varno
;
int
varno
;
int
varattno
;
int
sublevels_up
;
int
sublevels_up
;
}
contain_
whole_tuple_var
_context
;
}
contain_
var_reference
_context
;
typedef
struct
typedef
struct
{
{
...
@@ -39,8 +40,8 @@ typedef struct
...
@@ -39,8 +40,8 @@ typedef struct
static
bool
pull_varnos_walker
(
Node
*
node
,
static
bool
pull_varnos_walker
(
Node
*
node
,
pull_varnos_context
*
context
);
pull_varnos_context
*
context
);
static
bool
contain_
whole_tuple_var
_walker
(
Node
*
node
,
static
bool
contain_
var_reference
_walker
(
Node
*
node
,
contain_
whole_tuple_var
_context
*
context
);
contain_
var_reference
_context
*
context
);
static
bool
contain_var_clause_walker
(
Node
*
node
,
void
*
context
);
static
bool
contain_var_clause_walker
(
Node
*
node
,
void
*
context
);
static
bool
pull_var_clause_walker
(
Node
*
node
,
static
bool
pull_var_clause_walker
(
Node
*
node
,
pull_var_clause_context
*
context
);
pull_var_clause_context
*
context
);
...
@@ -129,10 +130,10 @@ pull_varnos_walker(Node *node, pull_varnos_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
* Detect whether a parsetree contains any references to
a specified
*
tuple of a given rtable entry (ie, a Var with varattno = 0)
.
*
attribute of a specified rtable entry
.
*
*
* NOTE: this is used on not-yet-planned expressions. It may therefore find
* 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
* 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)
...
@@ -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.
* SubPlan, we only need to look at the parameters passed to the subplan.
*/
*/
bool
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
.
varno
=
varno
;
context
.
varattno
=
varattno
;
context
.
sublevels_up
=
levelsup
;
context
.
sublevels_up
=
levelsup
;
/*
/*
...
@@ -154,15 +156,15 @@ contain_whole_tuple_var(Node *node, int varno, int levelsup)
...
@@ -154,15 +156,15 @@ contain_whole_tuple_var(Node *node, int varno, int levelsup)
*/
*/
if
(
node
&&
IsA
(
node
,
Query
))
if
(
node
&&
IsA
(
node
,
Query
))
return
query_tree_walker
((
Query
*
)
node
,
return
query_tree_walker
((
Query
*
)
node
,
contain_
whole_tuple_var
_walker
,
contain_
var_reference
_walker
,
(
void
*
)
&
context
,
true
);
(
void
*
)
&
context
,
true
);
else
else
return
contain_
whole_tuple_var
_walker
(
node
,
&
context
);
return
contain_
var_reference
_walker
(
node
,
&
context
);
}
}
static
bool
static
bool
contain_
whole_tuple_var
_walker
(
Node
*
node
,
contain_
var_reference
_walker
(
Node
*
node
,
contain_whole_tuple_var
_context
*
context
)
contain_var_reference
_context
*
context
)
{
{
if
(
node
==
NULL
)
if
(
node
==
NULL
)
return
false
;
return
false
;
...
@@ -171,8 +173,8 @@ contain_whole_tuple_var_walker(Node *node,
...
@@ -171,8 +173,8 @@ contain_whole_tuple_var_walker(Node *node,
Var
*
var
=
(
Var
*
)
node
;
Var
*
var
=
(
Var
*
)
node
;
if
(
var
->
varno
==
context
->
varno
&&
if
(
var
->
varno
==
context
->
varno
&&
var
->
var
levelsup
==
context
->
sublevels_up
&&
var
->
var
attno
==
context
->
varattno
&&
var
->
var
attno
==
InvalidAttrNumber
)
var
->
var
levelsup
==
context
->
sublevels_up
)
return
true
;
return
true
;
return
false
;
return
false
;
}
}
...
@@ -187,10 +189,10 @@ contain_whole_tuple_var_walker(Node *node,
...
@@ -187,10 +189,10 @@ contain_whole_tuple_var_walker(Node *node,
*/
*/
Expr
*
expr
=
(
Expr
*
)
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
))
context
))
return
true
;
return
true
;
if
(
contain_
whole_tuple_var
_walker
((
Node
*
)
expr
->
args
,
if
(
contain_
var_reference
_walker
((
Node
*
)
expr
->
args
,
context
))
context
))
return
true
;
return
true
;
return
false
;
return
false
;
...
@@ -202,16 +204,29 @@ contain_whole_tuple_var_walker(Node *node,
...
@@ -202,16 +204,29 @@ contain_whole_tuple_var_walker(Node *node,
context
->
sublevels_up
++
;
context
->
sublevels_up
++
;
result
=
query_tree_walker
((
Query
*
)
node
,
result
=
query_tree_walker
((
Query
*
)
node
,
contain_
whole_tuple_var
_walker
,
contain_
var_reference
_walker
,
(
void
*
)
context
,
true
);
(
void
*
)
context
,
true
);
context
->
sublevels_up
--
;
context
->
sublevels_up
--
;
return
result
;
return
result
;
}
}
return
expression_tree_walker
(
node
,
contain_
whole_tuple_var
_walker
,
return
expression_tree_walker
(
node
,
contain_
var_reference
_walker
,
(
void
*
)
context
);
(
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
* contain_var_clause
* Recursively scan a clause to discover whether it contains any Var nodes
* 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 @@
...
@@ -15,7 +15,7 @@
*
*
*
*
* IDENTIFICATION
* 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 @@
...
@@ -39,6 +39,7 @@
#include "optimizer/cost.h"
#include "optimizer/cost.h"
#include "parser/parse_func.h"
#include "parser/parse_func.h"
#include "parser/parse_oper.h"
#include "parser/parse_oper.h"
#include "parser/parsetree.h"
#include "utils/builtins.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/date.h"
#include "utils/int8.h"
#include "utils/int8.h"
...
@@ -818,7 +819,6 @@ eqjoinsel(PG_FUNCTION_ARGS)
...
@@ -818,7 +819,6 @@ eqjoinsel(PG_FUNCTION_ARGS)
{
{
#ifdef NOT_USED
/* see neqjoinsel() before removing me! */
#ifdef NOT_USED
/* see neqjoinsel() before removing me! */
Oid
opid
=
PG_GETARG_OID
(
0
);
Oid
opid
=
PG_GETARG_OID
(
0
);
#endif
#endif
Oid
relid1
=
PG_GETARG_OID
(
1
);
Oid
relid1
=
PG_GETARG_OID
(
1
);
AttrNumber
attno1
=
PG_GETARG_INT16
(
2
);
AttrNumber
attno1
=
PG_GETARG_INT16
(
2
);
...
@@ -2230,16 +2230,14 @@ string_to_datum(const char *str, Oid datatype)
...
@@ -2230,16 +2230,14 @@ string_to_datum(const char *str, Oid datatype)
*-------------------------------------------------------------------------
*-------------------------------------------------------------------------
*/
*/
static
Datum
static
void
genericcostestimate
(
PG_FUNCTION_ARGS
)
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
numIndexTuples
;
double
numIndexPages
;
double
numIndexPages
;
...
@@ -2275,33 +2273,134 @@ genericcostestimate(PG_FUNCTION_ARGS)
...
@@ -2275,33 +2273,134 @@ genericcostestimate(PG_FUNCTION_ARGS)
*
indexTotalCost
=
numIndexPages
+
*
indexTotalCost
=
numIndexPages
+
(
cpu_index_tuple_cost
+
cost_qual_eval
(
indexQuals
))
*
numIndexTuples
;
(
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
Datum
btcostestimate
(
PG_FUNCTION_ARGS
)
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
Datum
rtcostestimate
(
PG_FUNCTION_ARGS
)
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
Datum
hashcostestimate
(
PG_FUNCTION_ARGS
)
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
Datum
gistcostestimate
(
PG_FUNCTION_ARGS
)
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 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* 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
* NOTES
* Eventually, the index information should go through here, too.
* Eventually, the index information should go through here, too.
...
@@ -185,6 +185,36 @@ get_atttypmod(Oid relid, AttrNumber attnum)
...
@@ -185,6 +185,36 @@ get_atttypmod(Oid relid, AttrNumber attnum)
return
-
1
;
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 ---------- */
/* ---------- INDEX CACHE ---------- */
/* watch this space...
/* watch this space...
...
...
src/include/catalog/pg_proc.h
View file @
c23bc6fb
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* 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
* NOTES
* The script catalog/genbki.sh reads this file and generates .bki
* The script catalog/genbki.sh reads this file and generates .bki
...
@@ -210,9 +210,9 @@ DESCR("not equal");
...
@@ -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
-
));
DATA
(
insert
OID
=
89
(
version
PGUID
12
f
t
f
t
0
f
25
""
100
0
0
100
pgsql_version
-
));
DESCR
(
"PostgreSQL version string"
);
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"
);
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"
);
DESCR
(
"btree cost estimator"
);
/* OIDS 100 - 199 */
/* OIDS 100 - 199 */
...
@@ -789,7 +789,7 @@ DESCR("convert name to char()");
...
@@ -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
-
));
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"
);
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"
);
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
-
));
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");
...
@@ -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
-
));
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"
);
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"
);
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
-
));
DATA
(
insert
OID
=
774
(
gistgettuple
PGUID
12
f
t
f
t
2
f
23
"0 0"
100
0
0
100
gistgettuple
-
));
DESCR
(
"gist(internal)"
);
DESCR
(
"gist(internal)"
);
...
...
src/include/optimizer/var.h
View file @
c23bc6fb
...
@@ -7,7 +7,7 @@
...
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* 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 @@
...
@@ -17,6 +17,8 @@
#include "nodes/primnodes.h"
#include "nodes/primnodes.h"
extern
List
*
pull_varnos
(
Node
*
node
);
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_whole_tuple_var
(
Node
*
node
,
int
varno
,
int
levelsup
);
extern
bool
contain_var_clause
(
Node
*
node
);
extern
bool
contain_var_clause
(
Node
*
node
);
extern
List
*
pull_var_clause
(
Node
*
node
,
bool
includeUpperVars
);
extern
List
*
pull_var_clause
(
Node
*
node
,
bool
includeUpperVars
);
...
...
src/include/utils/lsyscache.h
View file @
c23bc6fb
...
@@ -6,7 +6,7 @@
...
@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
* 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);
...
@@ -21,6 +21,8 @@ extern AttrNumber get_attnum(Oid relid, char *attname);
extern
Oid
get_atttype
(
Oid
relid
,
AttrNumber
attnum
);
extern
Oid
get_atttype
(
Oid
relid
,
AttrNumber
attnum
);
extern
bool
get_attisset
(
Oid
relid
,
char
*
attname
);
extern
bool
get_attisset
(
Oid
relid
,
char
*
attname
);
extern
int32
get_atttypmod
(
Oid
relid
,
AttrNumber
attnum
);
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
RegProcedure
get_opcode
(
Oid
opno
);
extern
char
*
get_opname
(
Oid
opno
);
extern
char
*
get_opname
(
Oid
opno
);
extern
bool
op_mergejoinable
(
Oid
opno
,
Oid
ltype
,
Oid
rtype
,
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