Skip to content

Commit 2d76d75

Browse files
committed
Fix compute_scalar_stats() for case that all values exceed WIDTH_THRESHOLD.
The standard typanalyze functions skip over values whose detoasted size exceeds WIDTH_THRESHOLD (1024 bytes), so as to limit memory bloat during ANALYZE. However, we (I think I, actually :-() failed to consider the possibility that *every* non-null value in a column is too wide. While compute_minimal_stats() seems to behave reasonably anyway in such a case, compute_scalar_stats() just fell through and generated no pg_statistic entry at all. That's unnecessarily pessimistic: we can still produce valid stanullfrac and stawidth values in such cases, since we do include too-wide values in the average-width calculation. Furthermore, since the general assumption in this code is that too-wide values are probably all distinct from each other, it seems reasonable to set stadistinct to -1 ("all distinct"). Per complaint from Kadri Raudsepp. This has been like this since roughly neolithic times, so back-patch to all supported branches.
1 parent a29b6c3 commit 2d76d75

File tree

1 file changed

+15
-1
lines changed

1 file changed

+15
-1
lines changed

src/backend/commands/analyze.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2651,7 +2651,21 @@ compute_scalar_stats(VacAttrStatsP stats,
26512651
slot_idx++;
26522652
}
26532653
}
2654-
else if (nonnull_cnt == 0 && null_cnt > 0)
2654+
else if (nonnull_cnt > 0)
2655+
{
2656+
/* We found some non-null values, but they were all too wide */
2657+
Assert(nonnull_cnt == toowide_cnt);
2658+
stats->stats_valid = true;
2659+
/* Do the simple null-frac and width stats */
2660+
stats->stanullfrac = (double) null_cnt / (double) samplerows;
2661+
if (is_varwidth)
2662+
stats->stawidth = total_width / (double) nonnull_cnt;
2663+
else
2664+
stats->stawidth = stats->attrtype->typlen;
2665+
/* Assume all too-wide values are distinct, so it's a unique column */
2666+
stats->stadistinct = -1.0;
2667+
}
2668+
else if (null_cnt > 0)
26552669
{
26562670
/* We found only nulls; assume the column is entirely null */
26572671
stats->stats_valid = true;

0 commit comments

Comments
 (0)