Which table to drive from
The situation
A college placement dashboard runs one query on every page load:
sql
SELECT s.name, s.department, COUNT(a.id) AS applications
FROM students s
LEFT JOIN applications a ON a.student_id = s.id
WHERE s.batch_year = 2026
GROUP BY s.id, s.name, s.department
ORDER BY applications DESC
LIMIT 20;
It returned in 40 ms when the table held 800 students. It now takes 9 seconds with 24,000 students and 310,000 applications, and the dashboard is unusable.
The team checks the plan and finds a sequential scan on students, then a
hash join against a sequential scan of applications.
There is one index on students(id) (the primary key) and one on
applications(id). Nothing else. Statistics were last collected when the
table held 800 rows.
The filter batch_year = 2026 keeps about 6,000 of the 24,000 students. Which
join order does less work, and why?