diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 1999-09-09 02:36:04 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 1999-09-09 02:36:04 +0000 |
commit | 51db6455eac8aa5b0078cefffed51a6257ccbe1d (patch) | |
tree | b32ee35da610ebae0397bec58e0ad57143a21517 /src/backend/utils/adt/selfuncs.c | |
parent | 45500964f61b0ec671b84b1fdb988bad78f35473 (diff) | |
download | postgresql-51db6455eac8aa5b0078cefffed51a6257ccbe1d.tar.gz postgresql-51db6455eac8aa5b0078cefffed51a6257ccbe1d.zip |
Repair error noticed by Roberto Cornacchia: selectivity code
was rejecting negative attnums as bogus, which of course they are not.
Add code to get_attdisbursion to produce a useful value for OID attribute,
since VACUUM does not store stats for system attributes.
Also, repair bug that's been in eqjoinsel for a long time: it was taking
the max of the two columns' disbursions, whereas it should use the min.
Diffstat (limited to 'src/backend/utils/adt/selfuncs.c')
-rw-r--r-- | src/backend/utils/adt/selfuncs.c | 32 |
1 files changed, 23 insertions, 9 deletions
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index 883da87a275..1b2d58c075e 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.39 1999/08/21 00:56:18 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.40 1999/09/09 02:35:58 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -31,7 +31,7 @@ #include "utils/syscache.h" /* N is not a valid var/constant or relation id */ -#define NONVALUE(N) ((N) == -1) +#define NONVALUE(N) ((N) == 0) /* are we looking at a functional index selectivity request? */ #define FunctionalSelectivity(nIndKeys,attNum) ((attNum)==InvalidAttrNumber) @@ -170,7 +170,9 @@ eqsel(Oid opid, else { /* No VACUUM ANALYZE stats available, so make a guess using - * the disbursion stat (if we have that, which is unlikely...) + * the disbursion stat (if we have that, which is unlikely + * for a normal attribute; but for a system attribute we may + * be able to estimate it). */ selec = get_attdisbursion(relid, attno, 0.01); } @@ -366,7 +368,7 @@ eqjoinsel(Oid opid, float64 result; float64data num1, num2, - max; + min; result = (float64) palloc(sizeof(float64data)); if (NONVALUE(attno1) || NONVALUE(relid1) || @@ -376,11 +378,23 @@ eqjoinsel(Oid opid, { num1 = get_attdisbursion(relid1, attno1, 0.01); num2 = get_attdisbursion(relid2, attno2, 0.01); - max = (num1 > num2) ? num1 : num2; - if (max <= 0) - *result = 1.0; - else - *result = max; + /* + * The join selectivity cannot be more than num2, since each + * tuple in table 1 could match no more than num2 fraction of + * tuples in table 2 (and that's only if the table-1 tuple + * matches the most common value in table 2, so probably it's + * less). By the same reasoning it is not more than num1. + * The min is therefore an upper bound. + * + * XXX can we make a better estimate here? Using the nullfrac + * statistic might be helpful, for example. Assuming the operator + * is strict (does not succeed for null inputs) then the selectivity + * couldn't be more than (1-nullfrac1)*(1-nullfrac2), which might + * be usefully small if there are many nulls. How about applying + * the operator to the most common values? + */ + min = (num1 < num2) ? num1 : num2; + *result = min; } return result; } |