Skip to content

Commit 8c1144b

Browse files
committed
Avoid believing incomplete MCV-only stats in get_variable_range().
get_variable_range() would incautiously believe that statistics containing only an MCV list are sufficient to derive a range estimate. That's okay for an enum-like column that contains only MCVs, but otherwise the estimate could be pretty bad. Make it report that the range is indeterminate unless the MCVs plus nullfrac account for the whole table. I don't think this needs a dedicated test case, since a quick code coverage check verifies that the existing regression tests traverse all the alternatives. There is room to doubt that a future-proof test case could be built anyway, given that the submitted example accidentally doesn't fail before v11. Per bug #17207 from Simon Perepelitsa. Back-patch to v10. In principle this has been broken all along, but I'm hesitant to make such changes in 9.6, since if anyone is unhappy with 9.6.24's behavior there will be no second chance to fix it. Discussion: https://postgr.es/m/[email protected]
1 parent 7b5d4c2 commit 8c1144b

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

src/backend/utils/adt/selfuncs.c

+25-5
Original file line numberDiff line numberDiff line change
@@ -5841,15 +5841,35 @@ get_variable_range(PlannerInfo *root, VariableStatData *vardata,
58415841
/*
58425842
* If we have most-common-values info, look for extreme MCVs. This is
58435843
* needed even if we also have a histogram, since the histogram excludes
5844-
* the MCVs.
5844+
* the MCVs. However, if we *only* have MCVs and no histogram, we should
5845+
* be pretty wary of deciding that that is a full representation of the
5846+
* data. Proceed only if the MCVs represent the whole table (to within
5847+
* roundoff error).
58455848
*/
58465849
if (get_attstatsslot(&sslot, vardata->statsTuple,
58475850
STATISTIC_KIND_MCV, InvalidOid,
5848-
ATTSTATSSLOT_VALUES))
5851+
have_data ? ATTSTATSSLOT_VALUES :
5852+
(ATTSTATSSLOT_VALUES | ATTSTATSSLOT_NUMBERS)))
58495853
{
5850-
get_stats_slot_range(&sslot, opfuncoid, &opproc,
5851-
collation, typLen, typByVal,
5852-
&tmin, &tmax, &have_data);
5854+
bool use_mcvs = have_data;
5855+
5856+
if (!have_data)
5857+
{
5858+
double sumcommon = 0.0;
5859+
double nullfrac;
5860+
int i;
5861+
5862+
for (i = 0; i < sslot.nnumbers; i++)
5863+
sumcommon += sslot.numbers[i];
5864+
nullfrac = ((Form_pg_statistic) GETSTRUCT(vardata->statsTuple))->stanullfrac;
5865+
if (sumcommon + nullfrac > 0.99999)
5866+
use_mcvs = true;
5867+
}
5868+
5869+
if (use_mcvs)
5870+
get_stats_slot_range(&sslot, opfuncoid, &opproc,
5871+
collation, typLen, typByVal,
5872+
&tmin, &tmax, &have_data);
58535873
free_attstatsslot(&sslot);
58545874
}
58555875

0 commit comments

Comments
 (0)