Pick a depth. Each prompt opens in your AI pre-loaded with the lesson. Click a row to preview the prompt.
The failure mode this task exists to prevent is subtle and expensive: a load that half-succeeded, or succeeded against the wrong database, or produced uniform data because an environment variable was not what you thought. None of those announce themselves. You discover them four modules later when a query returns numbers that do not resemble anything in the lesson, and you spend an hour assuming you have misunderstood the material when in fact your events table has 900,000 rows instead of five million. Verification takes thirty seconds and it checks three independent things — that the volume is right, that the distribution is right, and that the physical size is right — because each one can be wrong while the others look fine.
One verification script per engine, checking volume, distribution and size, with the expected values for each scale so you can tell at a glance whether the load is sound.
-- ══ CHECK 1: VOLUME ════════════════════════════════════════════
SELECT 'users' t, count(*) FROM users
UNION ALL SELECT 'orders', count(*) FROM orders
UNION ALL SELECT 'events', count(*) FROM events;
-- t | count
-- --------+---------
-- users | 200000
-- orders | 2000000
-- events | 5000000
--
-- Expected, by scale:
-- small 20,000 / 200,000 / 500,000
-- default 200,000 / 2,000,000 / 5,000,000
-- large 2,000,000 / 20,000,000 / 50,000,000
-- ══ CHECK 2: DISTRIBUTION ══════════════════════════════════════
-- Volume can be right while the data is uniform, which silently
-- breaks modules 5 and 8. Check the shape, not just the count.
SELECT round(stddev(c) / avg(c), 2) AS cv, round(avg(c), 2) AS mean,
max(c) AS busiest_user
FROM (SELECT count(*) c FROM orders GROUP BY user_id) s;
-- cv | mean | busiest_user
-- ------+-------+--------------
-- 4.18 | 13.48 | 4102
--
-- cv above 2 = properly lopsided. Near 0 = uniform, reseed.
SELECT status, round(100.0*count(*)/sum(count(*)) OVER (),1) pct
FROM orders GROUP BY 1 ORDER BY 2 DESC;
-- paid 85.0 | shipped 12.0 | cart 10.0 | refunded 3.0
-- ══ CHECK 3: PHYSICAL SIZE ═════════════════════════════════════
SELECT relname,
pg_size_pretty(pg_table_size(oid)) AS heap,
pg_size_pretty(pg_indexes_size(oid)) AS indexes,
relpages,
round(reltuples / nullif(relpages, 0)) AS rows_per_page
FROM pg_class WHERE relname IN ('users','orders','events')
ORDER BY pg_table_size(oid) DESC;
-- relname | heap | indexes | relpages | rows_per_page
-- ---------+--------+---------+----------+---------------
-- events | 942 MB | 107 MB | 120576 | 41
-- orders | 260 MB | 43 MB | 32210 | 62
-- users | 24 MB | 4408 kB | 3012 | 66
--
-- Two things to confirm here:
-- 1. indexes are SMALL — only primary keys exist, as intended
-- 2. the total exceeds shared_buffers, so the working set will not
-- fit in cache. That is the condition the course needs.
SELECT pg_size_pretty(pg_database_size(current_database())) AS total;
-- 1418 MB
-- ══ CHECK 4: STATISTICS ARE PRESENT ════════════════════════════
-- Without ANALYZE the planner has no idea what is in these tables and
-- every estimate in module 2 will be nonsense.
SELECT relname, last_analyze, last_autoanalyze, n_live_tup
FROM pg_stat_user_tables WHERE relname IN ('users','orders','events');
-- last_analyze must not be null. If it is: ANALYZE users, orders, events;