Thread
Commits
-
vacuumdb: Fix --missing-stats-only for partitioned indexes.
- d2cea63065b3 19 (unreleased) landed
- 7e085aabd575 18 (unreleased) landed
-
Fix --missing-stats-only false positive for partitioned expression indexes
Baji Shaik <baji.pgdev@gmail.com> — 2026-06-16T15:25:52Z
Hi, I tested "vacuumdb --missing-stats-only" and found that it flags partitioned tables that have expression indexes, even after a full ANALYZE. Steps to reproduce: CREATE TABLE parent (a int, b int) PARTITION BY RANGE (a); CREATE TABLE child1 PARTITION OF parent FOR VALUES FROM (1) TO (100); CREATE TABLE child2 PARTITION OF parent FOR VALUES FROM (100) TO (200); CREATE INDEX ON parent ((a + b)); INSERT INTO parent SELECT i, i FROM generate_series(1, 199) i; ANALYZE; $ vacuumdb --missing-stats-only --analyze-only -v postgres 2>&1 | grep "public\." INFO: analyzing "public.parent" inheritance tree -- should not appear INFO: analyzing "public.child1" -- should not appear INFO: analyzing "public.child2" -- should not appear Running ANALYZE again doesn't help. The table is always flagged. This is because expression index stats check looks for stainherit=true rows on the partitioned index, but those never exist (only leaf indexes get stats). Fix is one line to skip the check when p.inherited is true. Patch attached. Thanks, Baji Shaik.
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Nathan Bossart <nathandbossart@gmail.com> — 2026-06-16T16:14:10Z
On Tue, Jun 16, 2026 at 10:25:52AM -0500, Baji Shaik wrote: > I tested "vacuumdb --missing-stats-only" and found that it flags > partitioned tables that have expression indexes, even after a full > ANALYZE. Thanks for reporting. - " OR EXISTS (SELECT NULL FROM pg_catalog.pg_attribute a\n" + " OR (NOT p.inherited" + " AND EXISTS (SELECT NULL FROM pg_catalog.pg_attribute a\n" I'm curious why you added this check to the beginning and surrounded the rest with parentheses. Wouldn't it be better to follow the example of the surrounding clauses and an "AND NOT p.inherited" somewhere in the middle? -- nathan
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Corey Huinker <corey.huinker@gmail.com> — 2026-06-16T16:23:17Z
On Tue, Jun 16, 2026 at 12:14 PM Nathan Bossart <nathandbossart@gmail.com> wrote: > On Tue, Jun 16, 2026 at 10:25:52AM -0500, Baji Shaik wrote: > > I tested "vacuumdb --missing-stats-only" and found that it flags > > partitioned tables that have expression indexes, even after a full > > ANALYZE. > > Thanks for reporting. > > - " OR EXISTS > (SELECT NULL FROM pg_catalog.pg_attribute a\n" > + " OR (NOT > p.inherited" > + " AND EXISTS > (SELECT NULL FROM pg_catalog.pg_attribute a\n" > > I'm curious why you added this check to the beginning and surrounded the > rest with parentheses. Wouldn't it be better to follow the example of the > surrounding clauses and an "AND NOT p.inherited" somewhere in the middle? > > -- > nathan I had a similar question and am toying around with refactoring it now. The rest of the patch checks out aside from that.
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Baji Shaik <baji.pgdev@gmail.com> — 2026-06-16T16:26:28Z
On Tue, Jun 16, 2026 at 11:14 AM Nathan Bossart <nathandbossart@gmail.com> wrote: > I'm curious why you added this check to the beginning and surrounded the > rest with parentheses. Wouldn't it be better to follow the example of the > surrounding clauses and an "AND NOT p.inherited" somewhere in the middle? Good point. v2 moves the check inside the EXISTS as "AND NOT p.inherited", consistent with how the inheritance sections below handle it. v2 attached. Thanks, Baji Shaik.
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Corey Huinker <corey.huinker@gmail.com> — 2026-06-16T16:40:11Z
On Tue, Jun 16, 2026 at 12:26 PM Baji Shaik <baji.pgdev@gmail.com> wrote: > On Tue, Jun 16, 2026 at 11:14 AM Nathan Bossart <nathandbossart@gmail.com> > wrote: > >> I'm curious why you added this check to the beginning and surrounded the >> rest with parentheses. Wouldn't it be better to follow the example of the >> surrounding clauses and an "AND NOT p.inherited" somewhere in the middle? > > > Good point. v2 moves the check inside the EXISTS as > "AND NOT p.inherited", consistent with how the inheritance > sections below handle it. > > v2 attached. > > Thanks, > Baji Shaik. > +1 The refactor I was testing differed only in having the new qual one line higher (above the attstattarget check vs below it). Looks good to me.
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Nathan Bossart <nathandbossart@gmail.com> — 2026-06-16T16:46:40Z
On Tue, Jun 16, 2026 at 12:40:11PM -0400, Corey Huinker wrote: > On Tue, Jun 16, 2026 at 12:26 PM Baji Shaik <baji.pgdev@gmail.com> wrote: >> Good point. v2 moves the check inside the EXISTS as >> "AND NOT p.inherited", consistent with how the inheritance >> sections below handle it. > > The refactor I was testing differed only in having the new qual one line > higher (above the attstattarget check vs below it). Looks good to me. We could remove the final "AND s.stainherit = p.inherited" in this part of the clause, too, right? -- nathan
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Baji Shaik <baji.pgdev@gmail.com> — 2026-06-16T17:09:00Z
On Tue, Jun 16, 2026 at 11:46 AM Nathan Bossart <nathandbossart@gmail.com> wrote: > We could remove the final "AND s.stainherit = p.inherited" in this part of > the clause, too, right? > Right. With NOT p.inherited already restricting this clause to the non-inherited case, the stainherit filter is redundant since index stats never have stainherit = true (only leaf indexes accumulate stats, always with stainherit = false). I verified this holds across partitioned, inherited, and mixed scenarios. Removed in v3. v3 attached. Thanks, Baji Shaik.
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Nathan Bossart <nathandbossart@gmail.com> — 2026-06-16T17:15:27Z
On Tue, Jun 16, 2026 at 12:09:00PM -0500, Baji Shaik wrote: > v3 attached. Here is a v4 with an updated commit message and a test case. -- nathan
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Baji Shaik <baji.pgdev@gmail.com> — 2026-06-16T17:23:35Z
On Tue, Jun 16, 2026 at 12:15 PM Nathan Bossart <nathandbossart@gmail.com> wrote: > Here is a v4 with an updated commit message and a test case. > Thanks for adding the test case. v4 looks good to me. Tested and verified. Thanks, Baji Shaik.
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Corey Huinker <corey.huinker@gmail.com> — 2026-06-16T17:25:27Z
On Tue, Jun 16, 2026 at 1:15 PM Nathan Bossart <nathandbossart@gmail.com> wrote: > On Tue, Jun 16, 2026 at 12:09:00PM -0500, Baji Shaik wrote: > > v3 attached. > > Here is a v4 with an updated commit message and a test case. > > -- > nathan > I know this is a corner-case of a corner-case, but if " AND s.stainherit OPERATOR(pg_catalog.=) p.inherited", we might then get a false negative from a situation like this: t2 inherits t1 t1 has ineritance stats but somehow not regular stats t2 dis-inherits from t1, t1 is no longer p.inherited = true, but inherited stats remain vacuumdb goes looking for matches, sees that t1 is p.inherited = false, find the old inherited stat row, not realizing it should have been looking for a non-inherits row.
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Nathan Bossart <nathandbossart@gmail.com> — 2026-06-16T17:51:28Z
On Tue, Jun 16, 2026 at 01:25:27PM -0400, Corey Huinker wrote: > I know this is a corner-case of a corner-case, but if " AND s.stainherit > OPERATOR(pg_catalog.=) p.inherited", we might then get a false negative > from a situation like this: > > t2 inherits t1 > t1 has ineritance stats but somehow not regular stats > t2 dis-inherits from t1, t1 is no longer p.inherited = true, but inherited > stats remain > > vacuumdb goes looking for matches, sees that t1 is p.inherited = false, > find the old inherited stat row, not realizing it should have been looking > for a non-inherits row. Since p.inherited is set based on the relkind, it could only change if the table was converted from partitioned to not partitioned. IIRC that's not currently possible. -- nathan
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Nathan Bossart <nathandbossart@gmail.com> — 2026-06-16T17:54:49Z
On Tue, Jun 16, 2026 at 12:51:28PM -0500, Nathan Bossart wrote: > On Tue, Jun 16, 2026 at 01:25:27PM -0400, Corey Huinker wrote: >> I know this is a corner-case of a corner-case, but if " AND s.stainherit >> OPERATOR(pg_catalog.=) p.inherited", we might then get a false negative >> from a situation like this: >> >> t2 inherits t1 >> t1 has ineritance stats but somehow not regular stats >> t2 dis-inherits from t1, t1 is no longer p.inherited = true, but inherited >> stats remain >> >> vacuumdb goes looking for matches, sees that t1 is p.inherited = false, >> find the old inherited stat row, not realizing it should have been looking >> for a non-inherits row. > > Since p.inherited is set based on the relkind, it could only change if the > table was converted from partitioned to not partitioned. IIRC that's not > currently possible. (Also, expression index stats are documented as always having stainherit = false...) -- nathan
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Corey Huinker <corey.huinker@gmail.com> — 2026-06-16T18:28:20Z
On Tue, Jun 16, 2026 at 1:54 PM Nathan Bossart <nathandbossart@gmail.com> wrote: > On Tue, Jun 16, 2026 at 12:51:28PM -0500, Nathan Bossart wrote: > > On Tue, Jun 16, 2026 at 01:25:27PM -0400, Corey Huinker wrote: > >> I know this is a corner-case of a corner-case, but if " AND > s.stainherit > >> OPERATOR(pg_catalog.=) p.inherited", we might then get a false negative > >> from a situation like this: > >> > >> t2 inherits t1 > >> t1 has ineritance stats but somehow not regular stats > >> t2 dis-inherits from t1, t1 is no longer p.inherited = true, but > inherited > >> stats remain > >> > >> vacuumdb goes looking for matches, sees that t1 is p.inherited = false, > >> find the old inherited stat row, not realizing it should have been > looking > >> for a non-inherits row. > > > > Since p.inherited is set based on the relkind, it could only change if > the > > table was converted from partitioned to not partitioned. IIRC that's not > > currently possible. > > (Also, expression index stats are documented as always having stainherit = > false...) Oh good. I like it when things are not problems.
-
Re: Fix --missing-stats-only false positive for partitioned expression indexes
Nathan Bossart <nathandbossart@gmail.com> — 2026-06-17T14:22:05Z
Committed. -- nathan