pg_squeeze

A tool to remove unused space from a relation.

Overview

PackageVersionCategoryLicenseLanguage
pg_squeeze1.9.4ADMINBSD-2-ClauseC
IDExtensionBinLibLoadCreateTrustRelocSchema
5040pg_squeezeNoYesYesYesNoNosqueeze
Relatedpg_repack pgstattuple pg_dirtyread pg_rewrite pg_column_tetris

Version

TypeRepoVersionPG VerPackageDeps
EXTPGDG1.9.41817161514pg_squeeze-
RPMPGDG1.9.41817161514pg_squeeze_$v-
DEBPGDG1.9.41817161514postgresql-$v-squeeze-
OS / PGPG18PG17PG16PG15PG14
el8.x86_64
el8.aarch64
el9.x86_64
el9.aarch64
el10.x86_64
el10.aarch64
d12.x86_64
d12.aarch64
d13.x86_64
d13.aarch64
u22.x86_64
u22.aarch64
u24.x86_64
u24.aarch64
u26.x86_64
u26.aarch64

Install

You can install pg_squeeze directly. First, make sure the PGDG repository is added and enabled:

pig repo add pgdg -u          # Add PGDG repo and update cache

Install the extension using pig or apt/yum/dnf:

pig install pg_squeeze;          # Install for current active PG version
pig ext install -y pg_squeeze -v 18  # PG 18
pig ext install -y pg_squeeze -v 17  # PG 17
pig ext install -y pg_squeeze -v 16  # PG 16
pig ext install -y pg_squeeze -v 15  # PG 15
pig ext install -y pg_squeeze -v 14  # PG 14
dnf install -y pg_squeeze_18       # PG 18
dnf install -y pg_squeeze_17       # PG 17
dnf install -y pg_squeeze_16       # PG 16
dnf install -y pg_squeeze_15       # PG 15
dnf install -y pg_squeeze_14       # PG 14
apt install -y postgresql-18-squeeze   # PG 18
apt install -y postgresql-17-squeeze   # PG 17
apt install -y postgresql-16-squeeze   # PG 16
apt install -y postgresql-15-squeeze   # PG 15
apt install -y postgresql-14-squeeze   # PG 14

Preload:

shared_preload_libraries = 'pg_squeeze';

Create Extension:

CREATE EXTENSION pg_squeeze;

Usage

Sources:

pg_squeeze removes bloat from a table and its indexes while allowing concurrent reads and writes. It copies live tuples to new storage and applies concurrent changes through logical decoding, avoiding the long exclusive lock of VACUUM FULL. Use it only after sizing replication slots, disk space, and the table’s replica identity.

Configure and Install

max_replication_slots = 1  # or add one to the existing requirement
shared_preload_libraries = 'pg_squeeze'
wal_level = logical       # required on PostgreSQL versions before 19

Restart PostgreSQL, then create the extension:

CREATE EXTENSION pg_squeeze;

The table must have an identity index. A primary key works with the default replica identity; otherwise select a suitable unique index with ALTER TABLE ... REPLICA IDENTITY USING INDEX.

Run an Ad-Hoc Squeeze

SELECT squeeze.squeeze_table('public', 'pgbench_accounts');

SELECT squeeze.squeeze_table(
  'public',
  'large_table',
  'large_table_cluster_idx',
  'target_tablespace'
);

The function starts background work and is not transactional in the ordinary SQL-function sense. Monitor the operation rather than assuming a surrounding ROLLBACK cancels it.

Schedule Tables and Monitor Work

INSERT INTO squeeze.tables (tabschema, tabname, schedule)
VALUES ('public', 'events', ('{30}', '{22}', NULL, NULL, '{3,5}'));

SELECT * FROM squeeze.get_active_workers();
SELECT * FROM squeeze.log ORDER BY finished DESC;
SELECT * FROM squeeze.errors;

The schedule tuple contains minutes, hours, days of month, months, and days of week. Registration also supports thresholds and placement options such as free_space_extra, min_size, vacuum_max_age, max_retry, clustering_index, relation/index tablespaces, and skip_analyze.

For automatic startup:

squeeze.worker_autostart = 'my_database'
squeeze.worker_role = 'postgres'

Version 1.9.4 and Operational Caveats

  • Version 1.9.4 fixes unsafe quoting in dynamically constructed ANALYZE, log, and error statements, including a superuser SQL-injection path. Upgrade earlier 1.9 builds promptly.
  • A full-table squeeze needs free disk space of roughly twice the combined size of the target table and its indexes.
  • Disruptive DDL, VACUUM FULL, CLUSTER, or TRUNCATE can make an in-progress squeeze abort. Coordinate schema changes and use max_retry deliberately.
  • Like other online rewrite tools, pg_squeeze changes row visibility and has documented MVCC caveats for concurrent sessions that retain old snapshots.
  • Configure pg_squeeze in shared_preload_libraries on the new cluster before pg_upgrade or dump/restore of a database containing the extension.
  • Current Pigsty packages cover PostgreSQL 14-18. For those versions, keep wal_level = logical; upstream’s relaxed PostgreSQL 19 rule does not apply to this package matrix yet.

Last Modified: 2026-08-10: extension update 08-10 (20223a3d)