2001-06-25 23:11:45 +02:00
|
|
|
/*-------------------------------------------------------------------------
|
|
|
|
*
|
|
|
|
* selfuncs.h
|
Restructure index access method API to hide most of it at the C level.
This patch reduces pg_am to just two columns, a name and a handler
function. All the data formerly obtained from pg_am is now provided
in a C struct returned by the handler function. This is similar to
the designs we've adopted for FDWs and tablesample methods. There
are multiple advantages. For one, the index AM's support functions
are now simple C functions, making them faster to call and much less
error-prone, since the C compiler can now check function signatures.
For another, this will make it far more practical to define index access
methods in installable extensions.
A disadvantage is that SQL-level code can no longer see attributes
of index AMs; in particular, some of the crosschecks in the opr_sanity
regression test are no longer possible from SQL. We've addressed that
by adding a facility for the index AM to perform such checks instead.
(Much more could be done in that line, but for now we're content if the
amvalidate functions more or less replace what opr_sanity used to do.)
We might also want to expose some sort of reporting functionality, but
this patch doesn't do that.
Alexander Korotkov, reviewed by Petr Jelínek, and rather heavily
editorialized on by me.
2016-01-18 01:36:59 +01:00
|
|
|
* Selectivity functions for standard operators, and assorted
|
|
|
|
* infrastructure for selectivity and cost estimation.
|
2001-06-25 23:11:45 +02:00
|
|
|
*
|
|
|
|
*
|
2024-01-04 02:49:05 +01:00
|
|
|
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
2001-06-25 23:11:45 +02:00
|
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
|
|
*
|
2010-09-20 22:08:53 +02:00
|
|
|
* src/include/utils/selfuncs.h
|
2001-06-25 23:11:45 +02:00
|
|
|
*
|
|
|
|
*-------------------------------------------------------------------------
|
|
|
|
*/
|
|
|
|
#ifndef SELFUNCS_H
|
|
|
|
#define SELFUNCS_H
|
|
|
|
|
2006-04-27 00:33:36 +02:00
|
|
|
#include "access/htup.h"
|
2019-08-19 21:51:38 +02:00
|
|
|
#include "fmgr.h"
|
2019-01-29 22:49:25 +01:00
|
|
|
#include "nodes/pathnodes.h"
|
2001-06-25 23:11:45 +02:00
|
|
|
|
|
|
|
|
2004-11-09 01:34:46 +01:00
|
|
|
/*
|
|
|
|
* Note: the default selectivity estimates are not chosen entirely at random.
|
|
|
|
* We want them to be small enough to ensure that indexscans will be used if
|
|
|
|
* available, for typical table densities of ~100 tuples/page. Thus, for
|
|
|
|
* example, 0.01 is not quite small enough, since that makes it appear that
|
|
|
|
* nearly all pages will be hit anyway. Also, since we sometimes estimate
|
|
|
|
* eqsel as 1/num_distinct, we probably want DEFAULT_NUM_DISTINCT to equal
|
|
|
|
* 1/DEFAULT_EQ_SEL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* default selectivity estimate for equalities such as "A = b" */
|
|
|
|
#define DEFAULT_EQ_SEL 0.005
|
|
|
|
|
|
|
|
/* default selectivity estimate for inequalities such as "A < b" */
|
|
|
|
#define DEFAULT_INEQ_SEL 0.3333333333333333
|
|
|
|
|
|
|
|
/* default selectivity estimate for range inequalities "A > b AND A < c" */
|
|
|
|
#define DEFAULT_RANGE_INEQ_SEL 0.005
|
|
|
|
|
Multirange datatypes
Multiranges are basically sorted arrays of non-overlapping ranges with
set-theoretic operations defined over them.
Since v14, each range type automatically gets a corresponding multirange
datatype. There are both manual and automatic mechanisms for naming multirange
types. Once can specify multirange type name using multirange_type_name
attribute in CREATE TYPE. Otherwise, a multirange type name is generated
automatically. If the range type name contains "range" then we change that to
"multirange". Otherwise, we add "_multirange" to the end.
Implementation of multiranges comes with a space-efficient internal
representation format, which evades extra paddings and duplicated storage of
oids. Altogether this format allows fetching a particular range by its index
in O(n).
Statistic gathering and selectivity estimation are implemented for multiranges.
For this purpose, stored multirange is approximated as union range without gaps.
This field will likely need improvements in the future.
Catversion is bumped.
Discussion: https://postgr.es/m/CALNJ-vSUpQ_Y%3DjXvTxt1VYFztaBSsWVXeF1y6gTYQ4bOiWDLgQ%40mail.gmail.com
Discussion: https://postgr.es/m/a0b8026459d1e6167933be2104a6174e7d40d0ab.camel%40j-davis.com#fe7218c83b08068bfffb0c5293eceda0
Author: Paul Jungwirth, revised by me
Reviewed-by: David Fetter, Corey Huinker, Jeff Davis, Pavel Stehule
Reviewed-by: Alvaro Herrera, Tom Lane, Isaac Morland, David G. Johnston
Reviewed-by: Zhihong Yu, Alexander Korotkov
2020-12-20 05:20:33 +01:00
|
|
|
/* default selectivity estimate for multirange inequalities "A > b AND A < c" */
|
|
|
|
#define DEFAULT_MULTIRANGE_INEQ_SEL 0.005
|
|
|
|
|
2004-11-09 01:34:46 +01:00
|
|
|
/* default selectivity estimate for pattern-match operators such as LIKE */
|
|
|
|
#define DEFAULT_MATCH_SEL 0.005
|
|
|
|
|
Improve selectivity estimation for assorted match-style operators.
Quite a few matching operators such as JSONB's @> used "contsel" and
"contjoinsel" as their selectivity estimators. That was a bad idea,
because (a) contsel is only a stub, yielding a fixed default estimate,
and (b) that default is 0.001, meaning we estimate these operators as
five times more selective than equality, which is surely pretty silly.
There's a good model for improving this in ltree's ltreeparentsel():
for any "var OP constant" query, we can try applying the operator
to all of the column's MCV and histogram values, taking the latter
as being a random sample of the non-MCV values. That code is
actually 100% generic, except for the question of exactly what
default selectivity ought to be plugged in when we don't have stats.
Hence, migrate the guts of ltreeparentsel() into the core code, provide
wrappers "matchingsel" and "matchingjoinsel" with a more-appropriate
default estimate, and use those for the non-geometric operators that
formerly used contsel (mostly JSONB containment operators and tsquery
matching).
Also apply this code to some match-like operators in hstore, ltree, and
pg_trgm, including the former users of ltreeparentsel as well as ones
that improperly used contsel. Since commit 911e70207 just created new
versions of those extensions that we haven't released yet, we can sneak
this change into those new versions instead of having to create an
additional generation of update scripts.
Patch by me, reviewed by Alexey Bashtanov
Discussion: https://postgr.es/m/12237.1582833074@sss.pgh.pa.us
2020-04-01 16:32:33 +02:00
|
|
|
/* default selectivity estimate for other matching operators */
|
|
|
|
#define DEFAULT_MATCHING_SEL 0.010
|
|
|
|
|
2004-11-09 01:34:46 +01:00
|
|
|
/* default number of distinct values in a table */
|
|
|
|
#define DEFAULT_NUM_DISTINCT 200
|
|
|
|
|
|
|
|
/* default selectivity estimate for boolean and null test nodes */
|
|
|
|
#define DEFAULT_UNK_SEL 0.005
|
|
|
|
#define DEFAULT_NOT_UNK_SEL (1.0 - DEFAULT_UNK_SEL)
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Clamp a computed probability estimate (which may suffer from roundoff or
|
|
|
|
* estimation errors) to valid range. Argument must be a float variable.
|
|
|
|
*/
|
|
|
|
#define CLAMP_PROBABILITY(p) \
|
|
|
|
do { \
|
|
|
|
if (p < 0.0) \
|
|
|
|
p = 0.0; \
|
|
|
|
else if (p > 1.0) \
|
|
|
|
p = 1.0; \
|
|
|
|
} while (0)
|
|
|
|
|
2021-03-30 09:52:46 +02:00
|
|
|
/*
|
|
|
|
* A set of flags which some selectivity estimation functions can pass back to
|
|
|
|
* callers to provide further details about some assumptions which were made
|
|
|
|
* during the estimation.
|
|
|
|
*/
|
|
|
|
#define SELFLAG_USED_DEFAULT (1 << 0) /* Estimation fell back on one
|
|
|
|
* of the DEFAULTs as defined
|
|
|
|
* above. */
|
|
|
|
|
|
|
|
typedef struct EstimationInfo
|
|
|
|
{
|
|
|
|
uint32 flags; /* Flags, as defined above to mark special
|
|
|
|
* properties of the estimation. */
|
|
|
|
} EstimationInfo;
|
2004-11-09 01:34:46 +01:00
|
|
|
|
2006-04-27 00:33:36 +02:00
|
|
|
/* Return data from examine_variable and friends */
|
2008-09-28 21:51:40 +02:00
|
|
|
typedef struct VariableStatData
|
2006-04-27 00:33:36 +02:00
|
|
|
{
|
|
|
|
Node *var; /* the Var or expression tree */
|
|
|
|
RelOptInfo *rel; /* Relation, or NULL if not identifiable */
|
|
|
|
HeapTuple statsTuple; /* pg_statistic tuple, or NULL if none */
|
|
|
|
/* NB: if statsTuple!=NULL, it must be freed when caller is done */
|
2008-09-28 21:51:40 +02:00
|
|
|
void (*freefunc) (HeapTuple tuple); /* how to free statsTuple */
|
2006-04-27 00:33:36 +02:00
|
|
|
Oid vartype; /* exposed type of expression */
|
Redesign get_attstatsslot()/free_attstatsslot() for more safety and speed.
The mess cleaned up in commit da0759600 is clear evidence that it's a
bug hazard to expect the caller of get_attstatsslot()/free_attstatsslot()
to provide the correct type OID for the array elements in the slot.
Moreover, we weren't even getting any performance benefit from that,
since get_attstatsslot() was extracting the real type OID from the array
anyway. So we ought to get rid of that requirement; indeed, it would
make more sense for get_attstatsslot() to pass back the type OID it found,
in case the caller isn't sure what to expect, which is likely in binary-
compatible-operator cases.
Another problem with the current implementation is that if the stats array
element type is pass-by-reference, we incur a palloc/memcpy/pfree cycle
for each element. That seemed acceptable when the code was written because
we were targeting O(10) array sizes --- but these days, stats arrays are
almost always bigger than that, sometimes much bigger. We can save a
significant number of cycles by doing one palloc/memcpy/pfree of the whole
array. Indeed, in the now-probably-common case where the array is toasted,
that happens anyway so this method is basically free. (Note: although the
catcache code will inline any out-of-line toasted values, it doesn't
decompress them. At the other end of the size range, it doesn't expand
short-header datums either. In either case, DatumGetArrayTypeP would have
to make a copy. We do end up using an extra array copy step if the element
type is pass-by-value and the array length is neither small enough for a
short header nor large enough to have suffered compression. But that
seems like a very acceptable price for winning in pass-by-ref cases.)
Hence, redesign to take these insights into account. While at it,
convert to an API in which we fill a struct rather than passing a bunch
of pointers to individual output arguments. That will make it less
painful if we ever want further expansion of what get_attstatsslot can
pass back.
It's certainly arguable that this is new development and not something to
push post-feature-freeze. However, I view it as primarily bug-proofing
and therefore something that's better to have sooner not later. Since
we aren't quite at beta phase yet, let's put it in.
Discussion: https://postgr.es/m/16364.1494520862@sss.pgh.pa.us
2017-05-13 21:14:39 +02:00
|
|
|
Oid atttype; /* actual type (after stripping relabel) */
|
|
|
|
int32 atttypmod; /* actual typmod (after stripping relabel) */
|
2012-02-16 23:33:28 +01:00
|
|
|
bool isunique; /* matches unique index or DISTINCT clause */
|
2017-05-05 18:18:48 +02:00
|
|
|
bool acl_ok; /* result of ACL check on table or column */
|
2006-04-27 00:33:36 +02:00
|
|
|
} VariableStatData;
|
|
|
|
|
|
|
|
#define ReleaseVariableStats(vardata) \
|
|
|
|
do { \
|
|
|
|
if (HeapTupleIsValid((vardata).statsTuple)) \
|
2017-09-07 18:06:23 +02:00
|
|
|
(vardata).freefunc((vardata).statsTuple); \
|
2006-04-27 00:33:36 +02:00
|
|
|
} while(0)
|
|
|
|
|
|
|
|
|
2016-03-24 03:01:35 +01:00
|
|
|
/*
|
|
|
|
* genericcostestimate is a general-purpose estimator that can be used for
|
|
|
|
* most index types. In some cases we use genericcostestimate as the base
|
|
|
|
* code and then incorporate additional index-type-specific knowledge in
|
|
|
|
* the type-specific calling function. To avoid code duplication, we make
|
|
|
|
* genericcostestimate return a number of intermediate values as well as
|
|
|
|
* its preliminary estimates of the output cost values. The GenericCosts
|
|
|
|
* struct includes all these values.
|
|
|
|
*
|
|
|
|
* Callers should initialize all fields of GenericCosts to zero. In addition,
|
|
|
|
* they can set numIndexTuples to some positive value if they have a better
|
|
|
|
* than default way of estimating the number of leaf index tuples visited.
|
Enhance nbtree ScalarArrayOp execution.
Commit 9e8da0f7 taught nbtree to handle ScalarArrayOpExpr quals
natively. This works by pushing down the full context (the array keys)
to the nbtree index AM, enabling it to execute multiple primitive index
scans that the planner treats as one continuous index scan/index path.
This earlier enhancement enabled nbtree ScalarArrayOp index-only scans.
It also allowed scans with ScalarArrayOp quals to return ordered results
(with some notable restrictions, described further down).
Take this general approach a lot further: teach nbtree SAOP index scans
to decide how to execute ScalarArrayOp scans (when and where to start
the next primitive index scan) based on physical index characteristics.
This can be far more efficient. All SAOP scans will now reliably avoid
duplicative leaf page accesses (just like any other nbtree index scan).
SAOP scans whose array keys are naturally clustered together now require
far fewer index descents, since we'll reliably avoid starting a new
primitive scan just to get to a later offset from the same leaf page.
The scan's arrays now advance using binary searches for the array
element that best matches the next tuple's attribute value. Required
scan key arrays (i.e. arrays from scan keys that can terminate the scan)
ratchet forward in lockstep with the index scan. Non-required arrays
(i.e. arrays from scan keys that can only exclude non-matching tuples)
"advance" without the process ever rolling over to a higher-order array.
Naturally, only required SAOP scan keys trigger skipping over leaf pages
(non-required arrays cannot safely end or start primitive index scans).
Consequently, even index scans of a composite index with a high-order
inequality scan key (which we'll mark required) and a low-order SAOP
scan key (which we won't mark required) now avoid repeating leaf page
accesses -- that benefit isn't limited to simpler equality-only cases.
In general, all nbtree index scans now output tuples as if they were one
continuous index scan -- even scans that mix a high-order inequality
with lower-order SAOP equalities reliably output tuples in index order.
This allows us to remove a couple of special cases that were applied
when building index paths with SAOP clauses during planning.
Bugfix commit 807a40c5 taught the planner to avoid generating unsafe
path keys: path keys on a multicolumn index path, with a SAOP clause on
any attribute beyond the first/most significant attribute. These cases
are now all safe, so we go back to generating path keys without regard
for the presence of SAOP clauses (just like with any other clause type).
Affected queries can now exploit scan output order in all the usual ways
(e.g., certain "ORDER BY ... LIMIT n" queries can now terminate early).
Also undo changes from follow-up bugfix commit a4523c5a, which taught
the planner to produce alternative index paths, with path keys, but
without low-order SAOP index quals (filter quals were used instead).
We'll no longer generate these alternative paths, since they can no
longer offer any meaningful advantages over standard index qual paths.
Affected queries thereby avoid all of the disadvantages that come from
using filter quals within index scan nodes. They can avoid extra heap
page accesses from using filter quals to exclude non-matching tuples
(index quals will never have that problem). They can also skip over
irrelevant sections of the index in more cases (though only when nbtree
determines that starting another primitive scan actually makes sense).
There is a theoretical risk that removing restrictions on SAOP index
paths from the planner will break compatibility with amcanorder-based
index AMs maintained as extensions. Such an index AM could have the
same limitations around ordered SAOP scans as nbtree had up until now.
Adding a pro forma incompatibility item about the issue to the Postgres
17 release notes seems like a good idea.
Author: Peter Geoghegan <pg@bowt.ie>
Author: Matthias van de Meent <boekewurm+postgres@gmail.com>
Reviewed-By: Heikki Linnakangas <hlinnaka@iki.fi>
Reviewed-By: Matthias van de Meent <boekewurm+postgres@gmail.com>
Reviewed-By: Tomas Vondra <tomas.vondra@enterprisedb.com>
Discussion: https://postgr.es/m/CAH2-Wz=ksvN_sjcnD1+Bt-WtifRA5ok48aDYnq3pkKhxgMQpcw@mail.gmail.com
2024-04-06 17:47:10 +02:00
|
|
|
* Similarly, they can set num_sa_scans to some value >= 1 for an index AM
|
|
|
|
* that doesn't necessarily perform exactly one primitive index scan per
|
|
|
|
* distinct combination of ScalarArrayOp array elements.
|
2016-03-24 03:01:35 +01:00
|
|
|
*/
|
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
/* These are the values the cost estimator must return to the planner */
|
|
|
|
Cost indexStartupCost; /* index-related startup cost */
|
|
|
|
Cost indexTotalCost; /* total index-related scan cost */
|
|
|
|
Selectivity indexSelectivity; /* selectivity of index */
|
|
|
|
double indexCorrelation; /* order correlation of index */
|
|
|
|
|
|
|
|
/* Intermediate values we obtain along the way */
|
|
|
|
double numIndexPages; /* number of leaf pages visited */
|
|
|
|
double numIndexTuples; /* number of leaf tuples visited */
|
|
|
|
double spc_random_page_cost; /* relevant random_page_cost value */
|
2019-08-13 06:53:41 +02:00
|
|
|
double num_sa_scans; /* # indexscans from ScalarArrayOpExprs */
|
2016-03-24 03:01:35 +01:00
|
|
|
} GenericCosts;
|
|
|
|
|
2008-09-28 21:51:40 +02:00
|
|
|
/* Hooks for plugins to get control when we ask for stats */
|
|
|
|
typedef bool (*get_relation_stats_hook_type) (PlannerInfo *root,
|
|
|
|
RangeTblEntry *rte,
|
|
|
|
AttrNumber attnum,
|
|
|
|
VariableStatData *vardata);
|
|
|
|
extern PGDLLIMPORT get_relation_stats_hook_type get_relation_stats_hook;
|
|
|
|
typedef bool (*get_index_stats_hook_type) (PlannerInfo *root,
|
|
|
|
Oid indexOid,
|
|
|
|
AttrNumber indexattnum,
|
|
|
|
VariableStatData *vardata);
|
|
|
|
extern PGDLLIMPORT get_index_stats_hook_type get_index_stats_hook;
|
|
|
|
|
2012-03-04 02:20:19 +01:00
|
|
|
/* Functions in selfuncs.c */
|
|
|
|
|
2006-04-27 02:46:59 +02:00
|
|
|
extern void examine_variable(PlannerInfo *root, Node *node, int varRelid,
|
|
|
|
VariableStatData *vardata);
|
2017-05-05 18:18:48 +02:00
|
|
|
extern bool statistic_proc_security_check(VariableStatData *vardata, Oid func_oid);
|
2006-04-27 02:46:59 +02:00
|
|
|
extern bool get_restriction_variable(PlannerInfo *root, List *args,
|
|
|
|
int varRelid,
|
|
|
|
VariableStatData *vardata, Node **other,
|
|
|
|
bool *varonleft);
|
|
|
|
extern void get_join_variables(PlannerInfo *root, List *args,
|
2008-08-16 02:01:38 +02:00
|
|
|
SpecialJoinInfo *sjinfo,
|
2006-04-27 02:46:59 +02:00
|
|
|
VariableStatData *vardata1,
|
2008-08-16 02:01:38 +02:00
|
|
|
VariableStatData *vardata2,
|
|
|
|
bool *join_is_reversed);
|
2011-09-04 21:41:49 +02:00
|
|
|
extern double get_variable_numdistinct(VariableStatData *vardata,
|
|
|
|
bool *isdefault);
|
Use query collation, not column's collation, while examining statistics.
Commit 5e0928005 changed the planner so that, instead of blindly using
DEFAULT_COLLATION_OID when invoking operators for selectivity estimation,
it would use the collation of the column whose statistics we're
considering. This was recognized as still being not quite the right
thing, but it seemed like a good incremental improvement. However,
shortly thereafter we introduced nondeterministic collations, and that
creates cases where operators can fail if they're passed the wrong
collation. We don't want planning to fail in cases where the query itself
would work, so this means that we *must* use the query's collation when
invoking operators for estimation purposes.
The only real problem this creates is in ineq_histogram_selectivity, where
the binary search might produce a garbage answer if we perform comparisons
using a different collation than the column's histogram is ordered with.
However, when the query's collation is significantly different from the
column's default collation, the estimate we previously generated would be
pretty irrelevant anyway; so it's not clear that this will result in
noticeably worse estimates in practice. (A follow-on patch will improve
this situation in HEAD, but it seems too invasive for back-patch.)
The patch requires changing the signatures of mcv_selectivity and allied
functions, which are exported and very possibly are used by extensions.
In HEAD, I just did that, but an API/ABI break of this sort isn't
acceptable in stable branches. Therefore, in v12 the patch introduces
"mcv_selectivity_ext" and so on, with signatures matching HEAD, and makes
the old functions into wrappers that assume DEFAULT_COLLATION_OID should
be used. That does not match the prior behavior, but it should avoid risk
of failure in most cases. (In practice, I think most extension datatypes
aren't collation-aware, so the change probably doesn't matter to them.)
Per report from James Lucas. Back-patch to v12 where the problem was
introduced.
Discussion: https://postgr.es/m/CAAFmbbOvfi=wMM=3qRsPunBSLb8BFREno2oOzSBS=mzfLPKABw@mail.gmail.com
2020-06-05 22:18:50 +02:00
|
|
|
extern double mcv_selectivity(VariableStatData *vardata,
|
|
|
|
FmgrInfo *opproc, Oid collation,
|
2006-04-27 19:52:40 +02:00
|
|
|
Datum constval, bool varonleft,
|
|
|
|
double *sumcommonp);
|
Use query collation, not column's collation, while examining statistics.
Commit 5e0928005 changed the planner so that, instead of blindly using
DEFAULT_COLLATION_OID when invoking operators for selectivity estimation,
it would use the collation of the column whose statistics we're
considering. This was recognized as still being not quite the right
thing, but it seemed like a good incremental improvement. However,
shortly thereafter we introduced nondeterministic collations, and that
creates cases where operators can fail if they're passed the wrong
collation. We don't want planning to fail in cases where the query itself
would work, so this means that we *must* use the query's collation when
invoking operators for estimation purposes.
The only real problem this creates is in ineq_histogram_selectivity, where
the binary search might produce a garbage answer if we perform comparisons
using a different collation than the column's histogram is ordered with.
However, when the query's collation is significantly different from the
column's default collation, the estimate we previously generated would be
pretty irrelevant anyway; so it's not clear that this will result in
noticeably worse estimates in practice. (A follow-on patch will improve
this situation in HEAD, but it seems too invasive for back-patch.)
The patch requires changing the signatures of mcv_selectivity and allied
functions, which are exported and very possibly are used by extensions.
In HEAD, I just did that, but an API/ABI break of this sort isn't
acceptable in stable branches. Therefore, in v12 the patch introduces
"mcv_selectivity_ext" and so on, with signatures matching HEAD, and makes
the old functions into wrappers that assume DEFAULT_COLLATION_OID should
be used. That does not match the prior behavior, but it should avoid risk
of failure in most cases. (In practice, I think most extension datatypes
aren't collation-aware, so the change probably doesn't matter to them.)
Per report from James Lucas. Back-patch to v12 where the problem was
introduced.
Discussion: https://postgr.es/m/CAAFmbbOvfi=wMM=3qRsPunBSLb8BFREno2oOzSBS=mzfLPKABw@mail.gmail.com
2020-06-05 22:18:50 +02:00
|
|
|
extern double histogram_selectivity(VariableStatData *vardata,
|
|
|
|
FmgrInfo *opproc, Oid collation,
|
2006-09-20 21:50:21 +02:00
|
|
|
Datum constval, bool varonleft,
|
2008-03-09 01:32:09 +01:00
|
|
|
int min_hist_size, int n_skip,
|
|
|
|
int *hist_size);
|
Use query collation, not column's collation, while examining statistics.
Commit 5e0928005 changed the planner so that, instead of blindly using
DEFAULT_COLLATION_OID when invoking operators for selectivity estimation,
it would use the collation of the column whose statistics we're
considering. This was recognized as still being not quite the right
thing, but it seemed like a good incremental improvement. However,
shortly thereafter we introduced nondeterministic collations, and that
creates cases where operators can fail if they're passed the wrong
collation. We don't want planning to fail in cases where the query itself
would work, so this means that we *must* use the query's collation when
invoking operators for estimation purposes.
The only real problem this creates is in ineq_histogram_selectivity, where
the binary search might produce a garbage answer if we perform comparisons
using a different collation than the column's histogram is ordered with.
However, when the query's collation is significantly different from the
column's default collation, the estimate we previously generated would be
pretty irrelevant anyway; so it's not clear that this will result in
noticeably worse estimates in practice. (A follow-on patch will improve
this situation in HEAD, but it seems too invasive for back-patch.)
The patch requires changing the signatures of mcv_selectivity and allied
functions, which are exported and very possibly are used by extensions.
In HEAD, I just did that, but an API/ABI break of this sort isn't
acceptable in stable branches. Therefore, in v12 the patch introduces
"mcv_selectivity_ext" and so on, with signatures matching HEAD, and makes
the old functions into wrappers that assume DEFAULT_COLLATION_OID should
be used. That does not match the prior behavior, but it should avoid risk
of failure in most cases. (In practice, I think most extension datatypes
aren't collation-aware, so the change probably doesn't matter to them.)
Per report from James Lucas. Back-patch to v12 where the problem was
introduced.
Discussion: https://postgr.es/m/CAAFmbbOvfi=wMM=3qRsPunBSLb8BFREno2oOzSBS=mzfLPKABw@mail.gmail.com
2020-06-05 22:18:50 +02:00
|
|
|
extern double generic_restriction_selectivity(PlannerInfo *root,
|
|
|
|
Oid oproid, Oid collation,
|
Improve selectivity estimation for assorted match-style operators.
Quite a few matching operators such as JSONB's @> used "contsel" and
"contjoinsel" as their selectivity estimators. That was a bad idea,
because (a) contsel is only a stub, yielding a fixed default estimate,
and (b) that default is 0.001, meaning we estimate these operators as
five times more selective than equality, which is surely pretty silly.
There's a good model for improving this in ltree's ltreeparentsel():
for any "var OP constant" query, we can try applying the operator
to all of the column's MCV and histogram values, taking the latter
as being a random sample of the non-MCV values. That code is
actually 100% generic, except for the question of exactly what
default selectivity ought to be plugged in when we don't have stats.
Hence, migrate the guts of ltreeparentsel() into the core code, provide
wrappers "matchingsel" and "matchingjoinsel" with a more-appropriate
default estimate, and use those for the non-geometric operators that
formerly used contsel (mostly JSONB containment operators and tsquery
matching).
Also apply this code to some match-like operators in hstore, ltree, and
pg_trgm, including the former users of ltreeparentsel as well as ones
that improperly used contsel. Since commit 911e70207 just created new
versions of those extensions that we haven't released yet, we can sneak
this change into those new versions instead of having to create an
additional generation of update scripts.
Patch by me, reviewed by Alexey Bashtanov
Discussion: https://postgr.es/m/12237.1582833074@sss.pgh.pa.us
2020-04-01 16:32:33 +02:00
|
|
|
List *args, int varRelid,
|
|
|
|
double default_selectivity);
|
2019-02-14 16:51:59 +01:00
|
|
|
extern double ineq_histogram_selectivity(PlannerInfo *root,
|
|
|
|
VariableStatData *vardata,
|
Improve ineq_histogram_selectivity's behavior for non-default orderings.
ineq_histogram_selectivity() can be invoked in situations where the
ordering we care about is not that of the column's histogram. We could
be considering some other collation, or even more drastically, the
query operator might not agree at all with what was used to construct
the histogram. (We'll get here for anything using scalarineqsel-based
estimators, so that's quite likely to happen for extension operators.)
Up to now we just ignored this issue and assumed we were dealing with
an operator/collation whose sort order exactly matches the histogram,
possibly resulting in junk estimates if the binary search gets confused.
It's past time to improve that, since the use of nondefault collations
is increasing. What we can do is verify that the given operator and
collation match what's recorded in pg_statistic, and use the existing
code only if so. When they don't match, instead execute the operator
against each histogram entry, and take the fraction of successes as our
selectivity estimate. This gives an estimate that is probably good to
about 1/histogram_size, with no assumptions about ordering. (The quality
of the estimate is likely to degrade near the ends of the value range,
since the two orderings probably don't agree on what is an extremal value;
but this is surely going to be more reliable than what we did before.)
At some point we might further improve matters by storing more than one
histogram calculated according to different orderings. But this code
would still be good fallback logic when no matches exist, so that is
not an argument for not doing this.
While here, also improve get_variable_range() to deal more honestly
with non-default collations.
This isn't back-patchable, because it requires adding another argument
to ineq_histogram_selectivity, and because it might have significant
impact on the estimation results for extension operators relying on
scalarineqsel --- mostly for the better, one hopes, but in any case
destabilizing plan choices in back branches is best avoided.
Per investigation of a report from James Lucas.
Discussion: https://postgr.es/m/CAAFmbbOvfi=wMM=3qRsPunBSLb8BFREno2oOzSBS=mzfLPKABw@mail.gmail.com
2020-06-05 22:55:16 +02:00
|
|
|
Oid opoid, FmgrInfo *opproc,
|
|
|
|
bool isgt, bool iseq,
|
Use query collation, not column's collation, while examining statistics.
Commit 5e0928005 changed the planner so that, instead of blindly using
DEFAULT_COLLATION_OID when invoking operators for selectivity estimation,
it would use the collation of the column whose statistics we're
considering. This was recognized as still being not quite the right
thing, but it seemed like a good incremental improvement. However,
shortly thereafter we introduced nondeterministic collations, and that
creates cases where operators can fail if they're passed the wrong
collation. We don't want planning to fail in cases where the query itself
would work, so this means that we *must* use the query's collation when
invoking operators for estimation purposes.
The only real problem this creates is in ineq_histogram_selectivity, where
the binary search might produce a garbage answer if we perform comparisons
using a different collation than the column's histogram is ordered with.
However, when the query's collation is significantly different from the
column's default collation, the estimate we previously generated would be
pretty irrelevant anyway; so it's not clear that this will result in
noticeably worse estimates in practice. (A follow-on patch will improve
this situation in HEAD, but it seems too invasive for back-patch.)
The patch requires changing the signatures of mcv_selectivity and allied
functions, which are exported and very possibly are used by extensions.
In HEAD, I just did that, but an API/ABI break of this sort isn't
acceptable in stable branches. Therefore, in v12 the patch introduces
"mcv_selectivity_ext" and so on, with signatures matching HEAD, and makes
the old functions into wrappers that assume DEFAULT_COLLATION_OID should
be used. That does not match the prior behavior, but it should avoid risk
of failure in most cases. (In practice, I think most extension datatypes
aren't collation-aware, so the change probably doesn't matter to them.)
Per report from James Lucas. Back-patch to v12 where the problem was
introduced.
Discussion: https://postgr.es/m/CAAFmbbOvfi=wMM=3qRsPunBSLb8BFREno2oOzSBS=mzfLPKABw@mail.gmail.com
2020-06-05 22:18:50 +02:00
|
|
|
Oid collation,
|
2019-02-14 16:51:59 +01:00
|
|
|
Datum constval, Oid consttype);
|
Use query collation, not column's collation, while examining statistics.
Commit 5e0928005 changed the planner so that, instead of blindly using
DEFAULT_COLLATION_OID when invoking operators for selectivity estimation,
it would use the collation of the column whose statistics we're
considering. This was recognized as still being not quite the right
thing, but it seemed like a good incremental improvement. However,
shortly thereafter we introduced nondeterministic collations, and that
creates cases where operators can fail if they're passed the wrong
collation. We don't want planning to fail in cases where the query itself
would work, so this means that we *must* use the query's collation when
invoking operators for estimation purposes.
The only real problem this creates is in ineq_histogram_selectivity, where
the binary search might produce a garbage answer if we perform comparisons
using a different collation than the column's histogram is ordered with.
However, when the query's collation is significantly different from the
column's default collation, the estimate we previously generated would be
pretty irrelevant anyway; so it's not clear that this will result in
noticeably worse estimates in practice. (A follow-on patch will improve
this situation in HEAD, but it seems too invasive for back-patch.)
The patch requires changing the signatures of mcv_selectivity and allied
functions, which are exported and very possibly are used by extensions.
In HEAD, I just did that, but an API/ABI break of this sort isn't
acceptable in stable branches. Therefore, in v12 the patch introduces
"mcv_selectivity_ext" and so on, with signatures matching HEAD, and makes
the old functions into wrappers that assume DEFAULT_COLLATION_OID should
be used. That does not match the prior behavior, but it should avoid risk
of failure in most cases. (In practice, I think most extension datatypes
aren't collation-aware, so the change probably doesn't matter to them.)
Per report from James Lucas. Back-patch to v12 where the problem was
introduced.
Discussion: https://postgr.es/m/CAAFmbbOvfi=wMM=3qRsPunBSLb8BFREno2oOzSBS=mzfLPKABw@mail.gmail.com
2020-06-05 22:18:50 +02:00
|
|
|
extern double var_eq_const(VariableStatData *vardata,
|
2022-09-20 23:08:57 +02:00
|
|
|
Oid oproid, Oid collation,
|
2019-02-14 16:51:59 +01:00
|
|
|
Datum constval, bool constisnull,
|
|
|
|
bool varonleft, bool negate);
|
Use query collation, not column's collation, while examining statistics.
Commit 5e0928005 changed the planner so that, instead of blindly using
DEFAULT_COLLATION_OID when invoking operators for selectivity estimation,
it would use the collation of the column whose statistics we're
considering. This was recognized as still being not quite the right
thing, but it seemed like a good incremental improvement. However,
shortly thereafter we introduced nondeterministic collations, and that
creates cases where operators can fail if they're passed the wrong
collation. We don't want planning to fail in cases where the query itself
would work, so this means that we *must* use the query's collation when
invoking operators for estimation purposes.
The only real problem this creates is in ineq_histogram_selectivity, where
the binary search might produce a garbage answer if we perform comparisons
using a different collation than the column's histogram is ordered with.
However, when the query's collation is significantly different from the
column's default collation, the estimate we previously generated would be
pretty irrelevant anyway; so it's not clear that this will result in
noticeably worse estimates in practice. (A follow-on patch will improve
this situation in HEAD, but it seems too invasive for back-patch.)
The patch requires changing the signatures of mcv_selectivity and allied
functions, which are exported and very possibly are used by extensions.
In HEAD, I just did that, but an API/ABI break of this sort isn't
acceptable in stable branches. Therefore, in v12 the patch introduces
"mcv_selectivity_ext" and so on, with signatures matching HEAD, and makes
the old functions into wrappers that assume DEFAULT_COLLATION_OID should
be used. That does not match the prior behavior, but it should avoid risk
of failure in most cases. (In practice, I think most extension datatypes
aren't collation-aware, so the change probably doesn't matter to them.)
Per report from James Lucas. Back-patch to v12 where the problem was
introduced.
Discussion: https://postgr.es/m/CAAFmbbOvfi=wMM=3qRsPunBSLb8BFREno2oOzSBS=mzfLPKABw@mail.gmail.com
2020-06-05 22:18:50 +02:00
|
|
|
extern double var_eq_non_const(VariableStatData *vardata,
|
2022-09-20 23:08:57 +02:00
|
|
|
Oid oproid, Oid collation,
|
2019-02-14 16:51:59 +01:00
|
|
|
Node *other,
|
|
|
|
bool varonleft, bool negate);
|
2001-06-25 23:11:45 +02:00
|
|
|
|
Allow planner to use expression-index stats for function calls in WHERE.
Previously, a function call appearing at the top level of WHERE had a
hard-wired selectivity estimate of 0.3333333, a kludge conveniently dated
in the source code itself to July 1992. The expectation at the time was
that somebody would soon implement estimator support functions analogous
to those for operators; but no such code has appeared, nor does it seem
likely to in the near future. We do have an alternative solution though,
at least for immutable functions on single relations: creating an
expression index on the function call will allow ANALYZE to gather stats
about the function's selectivity. But the code in clause_selectivity()
failed to make use of such data even if it exists.
Refactor so that that will happen. I chose to make it try this technique
for any clause type for which clause_selectivity() doesn't have a special
case, not just functions. To avoid adding unnecessary overhead in the
common case where we don't learn anything new, make selfuncs.c provide an
API that hooks directly to examine_variable() and then var_eq_const(),
rather than the previous coding which laboriously constructed an OpExpr
only so that it could be expensively deconstructed again.
I preserved the behavior that the default estimate for a function call
is 0.3333333. (For any other expression node type, it's 0.5, as before.)
I had originally thought to make the default be 0.5 across the board, but
changing a default estimate that's survived for twenty-three years seems
like something not to do without a lot more testing than I care to put
into it right now.
Per a complaint from Jehan-Guillaume de Rorthais. Back-patch into 9.5,
but not further, at least for the moment.
2015-09-25 00:35:46 +02:00
|
|
|
extern Selectivity boolvarsel(PlannerInfo *root, Node *arg, int varRelid);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern Selectivity booltestsel(PlannerInfo *root, BoolTestType booltesttype,
|
2008-08-14 20:48:00 +02:00
|
|
|
Node *arg, int varRelid,
|
|
|
|
JoinType jointype, SpecialJoinInfo *sjinfo);
|
2005-06-06 00:32:58 +02:00
|
|
|
extern Selectivity nulltestsel(PlannerInfo *root, NullTestType nulltesttype,
|
2008-08-14 20:48:00 +02:00
|
|
|
Node *arg, int varRelid,
|
|
|
|
JoinType jointype, SpecialJoinInfo *sjinfo);
|
2005-11-25 20:47:50 +01:00
|
|
|
extern Selectivity scalararraysel(PlannerInfo *root,
|
|
|
|
ScalarArrayOpExpr *clause,
|
|
|
|
bool is_join_clause,
|
2008-08-14 20:48:00 +02:00
|
|
|
int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo);
|
2024-01-05 00:36:19 +01:00
|
|
|
extern double estimate_array_length(PlannerInfo *root, Node *arrayexpr);
|
2006-01-14 01:14:12 +01:00
|
|
|
extern Selectivity rowcomparesel(PlannerInfo *root,
|
|
|
|
RowCompareExpr *clause,
|
2008-08-14 20:48:00 +02:00
|
|
|
int varRelid, JoinType jointype, SpecialJoinInfo *sjinfo);
|
2002-03-01 05:09:28 +01:00
|
|
|
|
2005-06-06 00:32:58 +02:00
|
|
|
extern void mergejoinscansel(PlannerInfo *root, Node *clause,
|
2011-03-12 22:30:36 +01:00
|
|
|
Oid opfamily, int strategy, bool nulls_first,
|
2007-12-08 22:05:11 +01:00
|
|
|
Selectivity *leftstart, Selectivity *leftend,
|
|
|
|
Selectivity *rightstart, Selectivity *rightend);
|
2001-06-25 23:11:45 +02:00
|
|
|
|
2005-06-06 00:32:58 +02:00
|
|
|
extern double estimate_num_groups(PlannerInfo *root, List *groupExprs,
|
2021-03-30 09:52:46 +02:00
|
|
|
double input_rows, List **pgset,
|
|
|
|
EstimationInfo *estinfo);
|
2002-11-20 00:22:00 +01:00
|
|
|
|
Avoid out-of-memory in a hash join with many duplicate inner keys.
The executor is capable of splitting buckets during a hash join if
too much memory is being used by a small number of buckets. However,
this only helps if a bucket's population is actually divisible; if
all the hash keys are alike, the tuples still end up in the same
new bucket. This can result in an OOM failure if there are enough
inner keys with identical hash values. The planner's cost estimates
will bias it against choosing a hash join in such situations, but not
by so much that it will never do so. To mitigate the OOM hazard,
explicitly estimate the hash bucket space needed by just the inner
side's most common value, and if that would exceed work_mem then
add disable_cost to the hash cost estimate.
This approach doesn't account for the possibility that two or more
common values would share the same hash value. On the other hand,
work_mem is normally a fairly conservative bound, so that eating
two or more times that much space is probably not going to kill us.
If we have no stats about the inner side, ignore this consideration.
There was some discussion of making a conservative assumption, but that
would effectively result in disabling hash join whenever we lack stats,
which seems like an overreaction given how seldom the problem manifests
in the field.
Per a complaint from David Hinkle. Although this could be viewed
as a bug fix, the lack of similar complaints weighs against back-
patching; indeed we waited for v11 because it seemed already rather
late in the v10 cycle to be making plan choice changes like this one.
Discussion: https://postgr.es/m/32013.1487271761@sss.pgh.pa.us
2017-08-15 20:05:46 +02:00
|
|
|
extern void estimate_hash_bucket_stats(PlannerInfo *root,
|
|
|
|
Node *hashkey, double nbuckets,
|
|
|
|
Selectivity *mcv_freq,
|
|
|
|
Selectivity *bucketsize_frac);
|
2020-11-24 09:45:00 +01:00
|
|
|
extern double estimate_hashagg_tablesize(PlannerInfo *root, Path *path,
|
2019-02-21 20:59:02 +01:00
|
|
|
const AggClauseCosts *agg_costs,
|
|
|
|
double dNumGroups);
|
2004-02-17 01:52:53 +01:00
|
|
|
|
2019-02-15 19:05:19 +01:00
|
|
|
extern List *get_quals_from_indexclauses(List *indexclauses);
|
|
|
|
extern Cost index_other_operands_eval_cost(PlannerInfo *root,
|
|
|
|
List *indexquals);
|
|
|
|
extern List *add_predicate_to_index_quals(IndexOptInfo *index,
|
|
|
|
List *indexQuals);
|
2016-03-24 03:01:35 +01:00
|
|
|
extern void genericcostestimate(PlannerInfo *root, IndexPath *path,
|
|
|
|
double loop_count,
|
|
|
|
GenericCosts *costs);
|
|
|
|
|
2012-03-04 02:20:19 +01:00
|
|
|
/* Functions in array_selfuncs.c */
|
|
|
|
|
|
|
|
extern Selectivity scalararraysel_containment(PlannerInfo *root,
|
|
|
|
Node *leftop, Node *rightop,
|
|
|
|
Oid elemtype, bool isEquality, bool useOr,
|
|
|
|
int varRelid);
|
|
|
|
|
2001-06-25 23:11:45 +02:00
|
|
|
#endif /* SELFUNCS_H */
|