| From: | Corey Huinker <corey(dot)huinker(at)gmail(dot)com> |
|---|---|
| To: | 125atishprak(at)gmail(dot)com, pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Subject: | Re: BUG #19857: Stats restore rejects empty arrays, losing range and array stats |
| Date: | 2026-11-10 17:01:13 |
| Message-ID: | CADkLM=dgnnbdMF3T4Him9O+h+-_MArPzZ13SMm4g8LpAXAqmeQ@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
On Tue, Nov 10, 2026 at 4:48 AM PG Bug reporting form <
noreply(at)postgresql(dot)org> wrote:
> The following bug has been logged on the website:
>
> Bug reference: 19857
> Logged by: Atish Prakash
> Email address: 125atishprak(at)gmail(dot)com
> PostgreSQL version: 18.6
> Operating system: Linux x86_64
> Description:
>
> If a range column has fewer than two non-empty values, ANALYZE stores an
> empty
> range length histogram. Restoring those statistics fails with a WARNING, so
> range_empty_frac is lost too, and estimates change a lot.
>
> CREATE TABLE r(a int4range);
> INSERT INTO r SELECT 'empty' FROM generate_series(1, 10000);
> ANALYZE r;
>
> Then dump with "pg_dump --statistics" and restore into an empty database:
>
> master: WARNING: "range_length_histogram" must be a one-dimensional
> array
> 18.6: WARNING: argument "range_length_histogram" must be specified
> when
> argument "range_empty_frac" is specified (message shortened)
>
> Estimates on master, with autovacuum disabled on the table so that a later
> ANALYZE
> does not replace the statistics:
>
> query actual before after
> SELECT * FROM r WHERE a <@ '[1,2)' 10000 10000 89
> SELECT * FROM r WHERE a && '[1,2)' 0 1 178
>
> A table with one non-empty value and 9,999 empty ones is affected the same
> way
> (estimate 9999 before, 87 after, for the first form of query, with actual
> 10000).
> Multirange columns also produce the warning.
>
> pg_upgrade loses them too: after an upgrade from 18.6 to 19rc1,
> range_empty_frac for
> table r went from 1 to NULL, and the first query above was estimated at 50
> rows.
>
> On 19rc1 and master the same check rejects most_common_elems when it is
> empty, which
> commit 261f89a976 makes common. An ordinary array column with all-distinct
> elements
> is enough, and tsvector columns are affected too:
>
> CREATE TABLE tags(id int, a int[]);
> INSERT INTO tags
> SELECT i, ARRAY[i, i + 1000000] FROM generate_series(1, 50000) i;
> ANALYZE tags;
>
> WARNING: "most_common_elems" must be a one-dimensional array
>
> query actual before after
> SELECT * FROM tags WHERE a @> '{5}' 1 3 ~270
> SELECT * FROM tags WHERE a && '{5,6}' 2 7 ~530
>
> Extended statistics are hit harder on master. An empty array in one
> expression's
> statistics rejects the statistics for every expression in that object,
> including
> unrelated ones:
>
> WARNING: could not parse "exprs": invalid element in expression -1
>
> Expected: the statistics restore as they were, without a warning.
>
> Cause: on master, pg_stats shows range_length_histogram as '{}' and pg_dump
> emits
> that. statatt_build_stavalues() requires a one-dimensional array, and an
> empty
> array has zero dimensions. On 18.6, pg_stats shows it as NULL, so pg_dump
> omits it
> while still emitting range_empty_frac, and the restore function rejects
> that
> pair.
>
> I have not written a patch.
>
> Found with dump and restore differential tests. I reproduced and checked
> the
> result myself.
>
>
Looking into this, probably a duplicate of 19842
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Tom Lane | 2026-11-10 18:53:01 | Re: BUG #19849: queries fail after ANALYZE with expression stats on arrays |
| Previous Message | Aleksander Alekseev | 2026-11-10 13:42:26 | Re: BUG #19602: Vuln46: citext split_part silently returns NULL for a zero field position instead of raising core sp |