pg_regresql 2.1.0

This Release
pg_regresql 2.1.0
Date
Status
Stable
Other Releases
Abstract
Trust pg_class statistics for query planning instead of physical file size; restore dumped statistics on 16/17
Released By
radim
License
PostgreSQL
Resources
Special Files
Tags

Extensions

pg_regresql 2.1.0
Trust pg_class statistics for query planning instead of physical file size; restore dumped statistics on 16/17

Documentation

README
PostgreSQL code

README

pg_regresql

PostgreSQL extension to force planner to use pg_class statistics instead of the estimates from the physical file size. This provides last-mile for RegreSQL query regression testing.

The Problem

As descibed in article Production query plans without production data planner ignores the relpages/reltuples stored in pg_class when checking the relation size.

Instead it calls smgrnblocks() to get the actual physical file size and scales statistics proportionally.

The reasononing for this is to avoid stale statistics (which can happen for example after TRUNCATE). The decision seems to be to use disk size being more reliable than potentially outdated catalog stats.

What pg_regresql Overrides

The extension hooks into get_relation_info_hook (fires after estimate_rel_size()) and replaces the planner’s physical-size estimates with catalog values.

Planner field Default source pg_regresql source
rel->pages smgrnblocks() via tableam pg_class.relpages
rel->tuples density × physical pages pg_class.reltuples
rel->allvisfrac relallvisible / physical pages pg_class.relallvisible / relpages
IndexOptInfo->pages RelationGetNumberOfBlocks() pg_class.relpages (index)
IndexOptInfo->tuples copied from rel->tuples pg_class.reltuples (index)

Installation

From PGXN

sudo pgxn install pg_regresql

From PostgreSQL source tree

# Point PG_SOURCE at your PostgreSQL source (must be configured)
make PG_SOURCE=/path/to/postgresql
make install PG_SOURCE=/path/to/postgresql

With PGXS (installed PostgreSQL)

make USE_PGXS=1
make install USE_PGXS=1

Usage

LOAD 'pg_regresql';

EXPLAIN SELECT ..

For all sessions on a test instance, add to postgresql.conf:

session_preload_libraries = 'pg_regresql'

Restoring statistics on PostgreSQL 16 and 17

CREATE EXTENSION pg_regresql; adds the two pg_restore_* functions pg_dump 18 and later call. Then load the dump, or just its statistics:

pg_dump --statistics-only -f stats.sql ...
psql -f stats.sql

On 16, drop the SET transaction_timeout = 0; line first. Extended statistics are not restored: 16/17 reject the pg_dependencies literal pg_dump 19 emits, so skip those statements. From 2.0, drop and recreate the extension; there is no update script. On 18+ nothing is created, core has the functions.

Use Cases

The primary use case is SQL query plan regression testing. Inject production statistics into a CI/test database and compare EXPLAIN output across schema migrations or PostgreSQL upgrades.

-- restore the stats
SELECT pg_restore_relation_stats(
    'schemaname', 'public',
    'relname', 'test_orders',
    'relpages', 123513::integer,
    'reltuples', 50000000::real,
    'relallvisible', 123513::integer
);

EXPLAIN SELECT * FROM test_orders WHERE created_at > '2024-06-01';

Other use cases are: - reproducing production query plans locally - simulating table growth and index strategy (what if scenarios) - partition planing

Compatibility

  • PostgreSQL 14+ for the planner hook (get_relation_info_hook)
  • Stats restore functions: 16 and 17 only; 18+ has them in core
  • Should work with pg_hint_plan, hypopg, and other hook-based extensions (not tested for now)

License

BSD 2-Clause License

Copyright © 2026 Radim Marek radim@boringsql.com