Question presented to candidate: "A report query that used to take 200 milliseconds now takes 30 seconds. Nobody knows why. How do you approach making it fast again โ what do you look at first, and what kinds of fixes do you reach for?"
What a strong answer should cover:
- Measure before changing anything: find the slow statements (
pg_stat_statements, the slow query log), reproduce with real parameters, and readEXPLAIN (ANALYZE, BUFFERS)to find the node where the time and the pages go - Read fewer rows: a missing or unusable index, a non-sargable predicate (function or cast on the column), an
ORDER BY ... LIMITwithout a matching index, stale statistics - Do less work per row: correlated subqueries or N+1 loops from the application, needless
DISTINCTor sorts, joins that multiply rows before aggregating - Avoid spills and wasted transfer: sorts and hashes exceeding
work_memgo to disk;SELECT *and unbounded result sets move data nobody uses;OFFSETpagination reads and discards rows - When the query is already as good as it gets: change the data shape (summary table, materialized view, partitioning, denormalisation) or the workload (cache, move analytics off the OLTP primary)
- Verify every change with the same measurement, one change at a time, and weigh the cost (an index slows writes)
Clarifying questions expected:
- How slow, how often does it run, and what is the target?
- What changed: data volume, a deploy, a new filter, a database upgrade?
- Is it a read on a busy OLTP database or a report that could run somewhere else?
Code / implementation expected: Yes โ read a plan, rewrite one query (sargable range, aggregate-then-join, index for ORDER BY ... LIMIT) and show the before/after plans.
Schema used by the examples: