On Sat, 12 Apr 2025 at 20:29, Corey Huinker <corey.huin...@gmail.com> wrote: >> >> at the *actual size* of the relation and takes that into account when >> scaling the statistics (see table_block_relation_estimate_size() in >> tableam.c). If the table sizes don't match between the two servers >> then there's no guarantees the planner will produce the same plan. > > Sorry that I didn't see this thread until now. I would like to note that > table_block_relation_estimate_size() determines the actual size of the > relation by asking pg_class, and the relevant values there are set by > pg_restore_relation_stats().
Sorry, this isn't correct. I suspect you're probably misreading the code. On a fleeting glance, you might have seen the "relpages = (BlockNumber) rel->rd_rel->relpages;" line and come to this conclusion. A more careful study will reveal the truth. Check for "curpages = RelationGetNumberOfBlocks(rel);" and an unconditional "*pages = curpages;". You might be getting confused because the code does look at the pg_class fields, but that's only to estimate the tuple density. When pg_class has those estimates, they're used to calculate the estimated density by doing reltuples / relpages, but that average rows per page is then applied to the *actual* number of pages in the relation. This method allows the stats to be scaled as the table grows and that take effect without waiting for vacuum or analyze to update the pg_class fields. The planner checks the current size of the table every time it plans a query. That's very well understood and documented. See [1]. David [1] https://www.postgresql.org/docs/current/row-estimation-examples.html#ROW-ESTIMATION-EXAMPLES