MySQL Indexes and Query Performance
An index is a data structure that trades storage and write cost for faster reads. The right index follows the filtering, join, and ordering pattern of a real query.
Composite Index Order
SELECT id, name, created_at FROM customers WHERE status = 'active' AND created_at >= '2026-01-01' ORDER BY created_at DESC LIMIT 50;
CREATE INDEX idx_customers_status_created
ON customers (status, created_at DESC);
The equality predicate comes first, followed by the range and ordering column. Index design depends on the full query, not on individual columns in isolation.
Read the Execution Plan
EXPLAIN ANALYZE SELECT id, name, created_at FROM customers WHERE status = 'active' ORDER BY created_at DESC LIMIT 50;
Look for the chosen index, estimated and actual row counts, loops, sorting, temporary tables, and expensive nested operations. Large estimate errors may indicate stale statistics or correlated data.
Covering Indexes
If the index contains every column needed by the query, MySQL may satisfy it without reading the base table. Covering indexes can be powerful for hot read paths but make indexes wider and writes more expensive.
Common Index Problems
- Creating one index for every column without considering query combinations.
- Using a function on the indexed column in the predicate.
- Leading wildcard searches such as
LIKE '%term'. - Sorting large unbounded result sets.
- Fetching every column with
SELECT *. - Keeping redundant prefix indexes after adding a composite index.
- Adding indexes without measuring write and storage impact.
Avoid Functions on Indexed Columns
-- Harder to use a normal index efficiently WHERE DATE(created_at) = '2026-07-16' -- Range form WHERE created_at >= '2026-07-16 00:00:00' AND created_at < '2026-07-17 00:00:00'
Slow Query Investigation
- Capture the exact SQL shape and execution time.
- Check frequency; a 50 ms query executed 10,000 times may matter more than one 2-second report.
- Run
EXPLAIN ANALYZEwith representative data. - Review indexes, row estimates, sorting, and temporary work.
- Check application behavior for N+1 queries and repeated calls.
- Apply one change and measure again.