PostgreSQL Performance Cheat Sheet

EXPLAIN, vacuum, planner settings, indexing, and practical tuning recipes.

View
StandardDetailedCompact
Export
Copy the compact sheet, download it, or print it.
Download
`D` dense toggle · `C` copy all

EXPLAIN and Plan Analysis

Read plans and compare query behavior.

EXPLAIN query

Show the planner's chosen execution plan.

sqlANYexplainplanner
sql
EXPLAIN SELECT * FROM orders WHERE customer_id = 42;

See summary for usage details.

EXPLAIN ANALYZE

Run the query and show actual timing and buffer usage.

sqlANYexplainanalyzebuffers
sql
EXPLAIN (ANALYZE, BUFFERS) SELECT * FROM orders WHERE customer_id = 42;

See summary for usage details.

EXPLAIN VERBOSE

Include more detail about output columns and active settings.

sqlANYexplainverbose
sql
EXPLAIN (ANALYZE, VERBOSE, BUFFERS, SETTINGS) SELECT * FROM orders WHERE customer_id = 42;

See summary for usage details.

EXPLAIN JSON format

Return the plan as machine-readable JSON.

sqlANYexplainjson
sql
EXPLAIN (ANALYZE, FORMAT JSON) SELECT * FROM orders;

See summary for usage details.

Enable auto_explain

Log slow query plans automatically in the server logs.

sqlANYauto_explainperformance
sql
LOAD 'auto_explain';
SET auto_explain.log_min_duration = '200ms';
SET auto_explain.log_analyze = on;

See summary for usage details.

Vacuum, Analyze, and Maintenance

Routine health tasks that keep PostgreSQL fast.

Vacuum one table

Reclaim dead tuples and maintain visibility data.

sqlANYvacuummaintenance
sql
VACUUM public.users;

See summary for usage details.

Vacuum analyze one table

Vacuum and refresh planner stats in one command.

sqlANYvacuumanalyze
sql
VACUUM (ANALYZE) public.users;

See summary for usage details.

VACUUM FULL table

Rewrite a bloated table more aggressively.

sqlANYvacuumfullmaintenance
sql
VACUUM (FULL, ANALYZE) public.users;

Requires more locking and space; use carefully.

Reindex table

Rebuild all indexes on a table.

sqlANYreindexmaintenance
sql
REINDEX TABLE public.users;

See summary for usage details.

Analyze verbose

Show extra detail while updating planner statistics.

sqlANYanalyzestats
sql
ANALYZE VERBOSE public.users;

See summary for usage details.

Show autovacuum setting

Check whether autovacuum is enabled.

sqlANYautovacuumsettings
sql
SHOW autovacuum;

See summary for usage details.

Planner Settings and Statistics

Inspect or tweak optimizer behavior during investigations.

Show work_mem

Inspect a setting that affects sort and hash memory usage.

sqlANYsettingswork_mem
sql
SHOW work_mem;

See summary for usage details.

Set LOCAL work_mem

Increase work_mem for the current transaction only.

sqlANYsettingswork_memsession
sql
SET LOCAL work_mem = '256MB';

See summary for usage details.

Show effective_cache_size

Inspect a planner estimate of OS cache availability.

sqlANYsettingsplanner
sql
SHOW effective_cache_size;

See summary for usage details.

Show random_page_cost

Inspect a cost parameter that influences index-vs-seqscan decisions.

sqlANYsettingsplannercost
sql
SHOW random_page_cost;

See summary for usage details.

Disable seqscan for investigation

Temporarily discourage sequential scans while investigating plans.

sqlANYplannerdebug
sql
SET enable_seqscan = off;

Do not use as a permanent performance fix.

Inspect pg_stats

Inspect statistics the planner uses.

sqlANYpg_statsplannerstats
sql
SELECT schemaname, tablename, attname, n_distinct, most_common_vals
FROM pg_stats
WHERE tablename = 'orders';

See summary for usage details.

High-value Query Performance Patterns

Recipes users often search for when tuning SQL.

Keyset pagination

Prefer keyset pagination over deep OFFSET scans for large result sets.

sqlANYpaginationperformance
sql
SELECT *
FROM orders
WHERE (created_at, order_id) < ('2026-03-01', 1000)
ORDER BY created_at DESC, order_id DESC
LIMIT 50;

See summary for usage details.

Select needed columns

Avoid fetching unnecessary columns, especially wide rows.

sqlANYquery-designperformance
sql
SELECT order_id, customer_id, total_amount FROM orders WHERE status = 'open';

See summary for usage details.

Covering index with INCLUDE

Use included columns to support index-only reads for certain queries.

sqlANYindexincludeperformance
sql
CREATE INDEX idx_orders_customer_created_inc
ON orders (customer_id, created_at DESC)
INCLUDE (status, total_amount);

See summary for usage details.

Batch updates

Chunk large writes into batches to reduce contention and WAL spikes.

sqlANYbatchupdateperformance
sql
UPDATE orders
SET archived_at = now()
WHERE order_id IN (
  SELECT order_id FROM orders WHERE created_at < now() - interval '1 year' LIMIT 10000
);

See summary for usage details.

Batch deletes

Delete in chunks to avoid huge transactions.

sqlANYbatchdeletemaintenance
sql
DELETE FROM audit_log
WHERE ctid IN (
  SELECT ctid FROM audit_log WHERE created_at < now() - interval '180 days' LIMIT 10000
);

See summary for usage details.

Create range-partitioned table

Partition large time-series tables by range.

sqlANYpartitioningtableperformance
sql
CREATE TABLE metrics (
  ts timestamptz NOT NULL,
  device_id bigint NOT NULL,
  value numeric NOT NULL
) PARTITION BY RANGE (ts);

See summary for usage details.

Attach partition

Add a partition for a date range.

sqlANYpartitioningddl
sql
CREATE TABLE metrics_2026_03 PARTITION OF metrics
FOR VALUES FROM ('2026-03-01') TO ('2026-04-01');

See summary for usage details.

Recommended next

No recommendations yet.