The optimiser costs plans from statistics gathered by ANALYZE. After a bulk load those statistics describe an empty table, so it plans for an empty table and the query takes minutes.
COPY orders FROM '/tmp/orders.csv' CSV;
ANALYZE orders; -- do not skip this
-- What it knows:
SELECT attname, n_distinct, most_common_vals
FROM pg_stats WHERE tablename = 'orders';
-- When it last ran:
SELECT relname, last_analyze, last_autoanalyze
FROM pg_stat_user_tables WHERE relname = 'orders';
Before ANALYZE: Nested Loop (rows=1) actual rows=482,110 94 s
After ANALYZE: Hash Join (rows=480000) actual rows=482,110 0.4 s
-- Autovacuum normally runs ANALYZE for you. It falls behind after a bulk
-- load, a restore, or a partition swap - exactly when it matters most.
Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.
Published 2026-08-25