Re: Preserve index stats during ALTER TABLE ... TYPE ... - Mailing list pgsql-hackers

From Bertrand Drouvot
Subject Re: Preserve index stats during ALTER TABLE ... TYPE ...
Date
Msg-id aO5GpA82ZDjV19r4@ip-10-97-1-34.eu-west-3.compute.internal
Whole thread Raw
In response to Re: Preserve index stats during ALTER TABLE ... TYPE ...  (Bertrand Drouvot <bertranddrouvot.pg@gmail.com>)
List pgsql-hackers
Hi,

On Fri, Oct 10, 2025 at 03:52:58PM +0000, Bertrand Drouvot wrote:
> The idea is to:
> 
> - store a List of savedIndexStats. The savedIndexStats struct would get the
> PgStat_StatTabEntry + all the information needed to be able to use 
> CompareIndexInfo() when restoring the stats (so that we can restore each PgStat_StatTabEntry
> in the right index).
> 
> - Iterate on all the indexes and populate this new list in AlteredTableInfo in
> ATPostAlterTypeParse().
> 
> - Iterate on all the indexes and use the list above and CompareIndexInfo() to
> restore the stats in ATExecAddIndex().
> 
> Will polish and share next week.

PFA v2 that handles partitioned tables/indexes.

A few words about its design:

I started by just creating a list of of PgStat_StatTabEntry + all the information
needed to be able to use CompareIndexInfo() when restoring the stats.

But that lead to O(P^2) when restoring the stats (for each new partition index
(P), it was scanning through all saved ones (P)), and could be non negligible.

For example, with 20K partitions and no rewrite:

-   89.64%     0.00%  postgres  postgres           [.] ATController
   - ATController
      - 79.23% ATRewriteCatalogs
         - 64.43% ATExecCmd
            - 56.53% ATExecAddIndex
               + 46.34% DefineIndex 
               + 10.19% ATExecAddIndex_RestoreStats
            + 5.29% ATExecAlterColumnType
            + 2.60% CommandCounterIncrement
         + 11.91% ATPostAlterTypeCleanup
         + 2.77% relation_open
      + 8.79% ATPrepCmd
      + 1.62% ATRewriteTables

We can see ATExecAddIndex_RestoreStats was not negligible at that time. That was
less of an issue when rewrite was involved:

-   89.35%     0.00%  postgres  postgres           [.] ATController
   - ATController
      + 51.24% ATRewriteTables
      - 33.89% ATRewriteCatalogs
         - 26.98% ATExecCmd
            - 22.16% ATExecAddIndex
               + 17.44% DefineIndex
                 4.71% ATExecAddIndex_RestoreStats
            + 3.58% ATExecAlterColumnType
            + 1.24% CommandCounterIncrement
         + 5.53% ATPostAlterTypeCleanup
         + 1.32% relation_open
      + 4.22% ATPrepCmd

So I added a hash table keyed by partition table OID, with each entry containing
a list of saved index stats for that partition. This way, restoration is now O(P)
instead of O(P²).

With the attached, the perf profile (again 20K partitions and no rewrite) is:

-   89.06%     0.00%  postgres  postgres           [.] ATController
   - ATController
      - 77.65% ATRewriteCatalogs
         - 61.57% ATExecCmd
            - 52.63% ATExecAddIndex
               + 51.16% DefineIndex
               + 1.47% ATExecAddIndex_RestoreStats
            + 5.96% ATExecAlterColumnType
            + 2.98% CommandCounterIncrement
         + 13.26% ATPostAlterTypeCleanup
         + 2.73% relation_open
      + 9.59% ATPrepCmd
      + 1.82% ATRewriteTables

As we can see, the ATExecAddIndex_RestoreStats impact is now around 1.5%, which
I think is acceptable given the benefit of preserving historical statistics.

Additional remarks:

- I initially tried using only CompareIndexInfo() for matching, but this fails
when multiple indexes exist on the same column(s). So I added the index name as
the primary matching check with CompareIndexInfo() kept as a sanity check (I think
that it could be removed).

- The new resources are allocated in the PortalContext, it's a short lived one so
the patch does not free them explicitly.

- Much more tests have been added as compared to v1.

Regards,

-- 
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

Attachment

pgsql-hackers by date:

Previous
From: Heikki Linnakangas
Date:
Subject: Re: get rid of RM_HEAP2_ID
Next
From: Xuneng Zhou
Date:
Subject: Re: Implement waiting for wal lsn replay: reloaded