Query, meet consequence
Point a SQL query at a table and watch what the database actually does. You pick the table size, whether the filtered column is indexed, how many rows the WHERE clause matches, and how many tables you join — and the plan comes back: rows scanned versus rows returned, a cost figure, an estimated latency, and a verdict. The reveal is the gap between fast today and fast because it's correct: a query that returns in milliseconds can still be a full table scan quietly waiting to fall over as the data grows. Runs entirely in your browser (0 uploads, works offline).
How to use it
- Choose a table size (10K → 100M rows) and set how many rows the filter matches with the selectivity slider.
- Toggle Index on the WHERE column on and off, and add up to three joined tables.
- Read the plan: the bar shows how much of the table was scanned versus returned; the stats show rows scanned, cost units and estimated latency; the verdict reads fast / ok / slow.
- Watch what happens when you bump the same query from 1M to 100M rows — a full scan that felt fast tips into slow, while an index seek stays fast.
What this clears up (the fundamentals)
- Rows scanned, not wall-clock, is the tell. A query that returns quickly can still read every row in the table. Latency hides the work; the scan count exposes it.
- A full table scan's cost grows with the table. Fast on 10K rows means nothing — the same scan on 100M rows reads 10,000× more, so it degrades exactly when your data succeeds.
- An index seek jumps straight to matching rows. With an index on the filtered column the planner reads only the rows it returns, so cost tracks the result size, not the table size.
- Joins multiply the work. Each joined table inflates the cost of whatever rows you're already scanning — a full scan under a join is expensive twice over.
- Selectivity decides whether an index even helps. If the
WHEREclause matches most of the table, a seek stops being cheap; a very selective filter is where an index pays off most.
Where it's used
A Data-track drill for the "Data Before Models" lesson — the fastest way to build the instinct for reading a query plan instead of trusting a stopwatch. It's a miatz build-lab concept playable: play the widget here, then learn to build the real thing (a live EXPLAIN flame graph over a seeded database) in the lab.
FAQ
What's the difference between a full scan and an index seek?
A full table scan reads every row and checks each against the WHERE clause; an index seek uses an index to jump straight to the matching rows without touching the rest. Both return the same result — the seek just does far less work.
Why does a "fast" query get flagged?
Because speed on today's data isn't the same as scaling. The tool marks a full scan even when its latency is low, because that same scan reads every row: 10× the table means 10× the work. The verdict tells you it's quick now; the scan type tells you why it won't stay that way.
What is selectivity?
The fraction of rows the filter matches. A very selective filter (say 0.1%) returns few rows and is where an index helps most; a low-selectivity filter that matches most of the table gets little benefit from an index because you're reading most of it anyway.
Is anything uploaded?
No. The table size, index toggle, selectivity, joins and the whole plan are computed in your browser — nothing is transmitted or stored. Turn off your Wi-Fi and it still works.
Limits
A teaching model, not a real query planner. It uses a simple cost model (rows scanned, inflated by joins) and a rough latency estimate; a production optimizer weighs statistics, index depth, cache state, join algorithms and hardware. Use it to build the "read the scan, not the clock" instinct, then confirm against a real EXPLAIN ANALYZE on your own database.
Related
Part of the Demystify Playgrounds. Explore the rest from the Playgrounds home.
Bookmark this page (Ctrl+D, or ⌘D on Mac) — it works offline the next time you need it.