The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Create a tablespace | CREATE TABLESPACE fastspace LOCATION '/srv/postgresql/fastspace'; | View examples |
| List tablespaces | SELECT spcname, pg_tablespace_location(oid)
FROM pg_tablespace; | View examples |
| Grant create privilege | GRANT CREATE ON TABLESPACE fastspace TO app_owner; | View examples |
| Place a new table | CREATE TABLE app.events (id bigint, payload jsonb) TABLESPACE fastspace; | View examples |
| Place a new index | CREATE INDEX events_id_idx
ON app.events (id) TABLESPACE fastspace; | View examples |
| Move a table | ALTER TABLE app.events SET TABLESPACE fastspace; | View examples |
| Set heap fillfactor | ALTER TABLE app.sessions SET (fillfactor = 80); | View examples |
| Reset heap fillfactor | ALTER TABLE app.sessions RESET (fillfactor); | View examples |
| Set index fillfactor | ALTER INDEX app.events_tenant_time_idx
SET (fillfactor = 80); | View examples |
| Repack an index concurrently | REINDEX INDEX CONCURRENTLY app.events_tenant_time_idx; | View examples |
| Prefer external storage | ALTER TABLE app.events ALTER COLUMN payload
SET STORAGE EXTERNAL; | View examples |
| Set TOAST autovacuum scale | ALTER TABLE app.events
SET (toast.autovacuum_vacuum_scale_factor = 0.05); | View examples |
| Set a vacuum scale factor | ALTER TABLE app.job_queue
SET (autovacuum_vacuum_scale_factor = 0.02); | View examples |
| Reset table overrides | ALTER TABLE app.job_queue RESET (autovacuum_vacuum_scale_factor); | View examples |
| Show a relation tablespace | SELECT reltablespace
FROM pg_class
WHERE oid = 'app.events'::regclass; | View examples |
| Measure a tablespace | SELECT pg_size_pretty(pg_tablespace_size('fastspace')); | View examples |
| Drop an empty tablespace | DROP TABLESPACE fastspace; | View examples |
Tablespaces map database objects to administrator-managed filesystem locations, while storage parameters tune individual heap, index, TOAST, and autovacuum behavior. These controls affect physical layout and maintenance—not logical backup boundaries—and poor choices can trade one bottleneck for another.
Step by step
Detailed examples
Provision tablespaces as cluster infrastructure
Only a superuser can create a tablespace. The absolute directory must already exist, be empty, and be owned by the PostgreSQL operating-system account; CREATE TABLESPACE cannot run inside a transaction block. The path is a symlink-backed part of the same cluster, not portable independent storage.
CREATE TABLESPACE fastspace
OWNER app_owner
LOCATION '/srv/postgresql/fastspace'
WITH (random_page_cost = 1.1, effective_io_concurrency = 200); Note: Provision and secure the directory at the OS layer first; run outside a transaction in an approved maintenance window.
Place heaps and indexes according to measured I/O needs
TABLESPACE clauses choose initial placement; defaults come from default_tablespace and temp_tablespaces. Moving an existing relation rewrites or copies physical data and holds strong locks, so budget capacity on source, destination, replicas, and backups. A partitioned parent has no storage; place each leaf.
CREATE INDEX CONCURRENTLY orders_created_idx
ON app.orders (created_at)
TABLESPACE fastspace; Note: CONCURRENTLY reduces write blocking but takes longer, performs extra work, and cannot run inside a transaction block.
Reserve heap page space for update-heavy rows
Heap fillfactor ranges from 10 to 100 and affects how future INSERT and rewrite operations pack pages. Lower values leave room for same-page updates, improving the chance of HOT updates when indexed columns are unchanged, at the cost of a larger table and more scan I/O. Existing pages are not repacked merely by changing the setting.
ALTER TABLE app.sessions SET (fillfactor = 80);
-- Apply to existing pages later with VACUUM FULL, CLUSTER, or a rewrite tool. Note: VACUUM FULL and CLUSTER require strong locks; do not run them casually in production.
Tune index fillfactor for write patterns
B-tree fillfactor controls initial leaf-page packing: the default is 90, while lower values can reduce early page splits on insert-heavy indexes. Overly low values waste cache and storage. Index storage parameters differ by access method, so verify support and rebuild if existing pages must be repacked.
CREATE INDEX CONCURRENTLY events_tenant_time_idx
ON app.events (tenant_id, occurred_at)
WITH (fillfactor = 80); Control large-value storage with TOAST-aware settings
TOAST stores compressible or oversized values out of line when needed. Column STORAGE and COMPRESSION preferences affect future writes, not existing values, and MAIN only prefers inline storage rather than guaranteeing it. Disabling autovacuum on a table does not automatically protect its TOAST table from bloat.
ALTER TABLE app.events ALTER COLUMN payload SET COMPRESSION lz4; Note: The cluster must support the method; unchanged existing values keep their prior compression until rewritten.
Override autovacuum only for exceptional tables
Per-table thresholds can make high-churn or append-heavy relations maintain statistics and dead tuples sooner. Overrides multiply operational complexity and should be based on observed modification rates and table size. Setting autovacuum_enabled=false does not prevent wraparound vacuum and creates serious bloat and statistics risks.
ALTER TABLE app.job_queue SET (
autovacuum_vacuum_scale_factor = 0.02,
autovacuum_vacuum_threshold = 1000,
autovacuum_analyze_scale_factor = 0.01
); Inventory placement before changing or dropping storage
Use supported size functions and catalogs to find relations in each tablespace. DROP TABLESPACE requires it to be empty across every database in the cluster, and the directory should be removed only after PostgreSQL unregisters it. Logical dumps preserve tablespace declarations unless options suppress them, but do not copy tablespace files.
SELECT n.nspname, c.relname, t.spcname, pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_tablespace t ON t.oid = c.reltablespace
WHERE c.relkind IN ('r', 'm', 'i')
ORDER BY pg_total_relation_size(c.oid) DESC; Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- PostgreSQL Global Development GroupTablespacespostgresql.org
- PostgreSQL Global Development GroupCREATE TABLESPACEpostgresql.org
- PostgreSQL Global Development GroupALTER TABLESPACEpostgresql.org
- PostgreSQL Global Development GroupDROP TABLESPACEpostgresql.org
- PostgreSQL Global Development GroupCREATE TABLE and Storage Parameterspostgresql.org
- PostgreSQL Global Development GroupALTER TABLEpostgresql.org
- PostgreSQL Global Development GroupCREATE INDEXpostgresql.org
- PostgreSQL Global Development GroupTOASTpostgresql.org
- PostgreSQL Global Development GroupRoutine Vacuumingpostgresql.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



