Introduction
Fixing N+1 queries with select_related/prefetch_related or selectinload (see the previous post) gets you down to a small, sane number of queries per request. The next bottleneck is what each query costs once the table has millions of rows — and that is almost always about indexing.
An index turns "scan every row" into "look it up directly." Skip it, and a query that's instant in development takes seconds once real data volume shows up in production.
How Indexes Work: The B-Tree Intuition
Without an index, a WHERE clause forces a sequential scan: the database reads every row and checks the condition — O(n), cost grows linearly with table size.






