1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Make estimation of mergejoin scan selectivities more robust, per recent

example from RaÇl GutiÅrrez.
This commit is contained in:
Tom Lane
2003-01-22 20:16:42 +00:00
parent c7b4047234
commit c4d0ff32e9
2 changed files with 41 additions and 11 deletions

View File

@ -15,7 +15,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.127 2003/01/20 18:54:59 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/adt/selfuncs.c,v 1.128 2003/01/22 20:16:42 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -1742,7 +1742,9 @@ mergejoinscansel(Query *root, Node *clause,
rsortop,
ltop,
gtop,
revltop;
leop,
revgtop,
revleop;
Datum leftmax,
rightmax;
double selec;
@ -1780,35 +1782,49 @@ mergejoinscansel(Query *root, Node *clause,
/* Look up the "left < right" and "left > right" operators */
op_mergejoin_crossops(opno, &ltop, &gtop, NULL, NULL);
/* Look up the "right < left" operator */
revltop = get_commutator(gtop);
if (!OidIsValid(revltop))
return; /* shouldn't happen */
/* Look up the "left <= right" operator */
leop = get_negator(gtop);
if (!OidIsValid(leop))
return; /* insufficient info in catalogs */
/* Look up the "right > left" operator */
revgtop = get_commutator(ltop);
if (!OidIsValid(revgtop))
return; /* insufficient info in catalogs */
/* Look up the "right <= left" operator */
revleop = get_negator(revgtop);
if (!OidIsValid(revleop))
return; /* insufficient info in catalogs */
/*
* Now, the fraction of the left variable that will be scanned is the
* fraction that's <= the right-side maximum value. But only believe
* non-default estimates, else stick with our 1.0.
*/
selec = scalarineqsel(root, ltop, false, left,
selec = scalarineqsel(root, leop, false, left,
rightmax, right->vartype);
if (selec != DEFAULT_INEQ_SEL)
*leftscan = selec;
/* And similarly for the right variable. */
selec = scalarineqsel(root, revltop, false, right,
selec = scalarineqsel(root, revleop, false, right,
leftmax, left->vartype);
if (selec != DEFAULT_INEQ_SEL)
*rightscan = selec;
/*
* Only one of the two fractions can really be less than 1.0; believe
* the smaller estimate and reset the other one to exactly 1.0.
* the smaller estimate and reset the other one to exactly 1.0. If we
* get exactly equal estimates (as can easily happen with self-joins),
* believe neither.
*/
if (*leftscan > *rightscan)
*leftscan = 1.0;
else
else if (*leftscan < *rightscan)
*rightscan = 1.0;
else
*leftscan = *rightscan = 1.0;
}
/*