Implementing Indexes for Performance
The University database starts small, but imagine thousands of students and decades of enrollment history. Without indexes, every query would scan entire tables. Indexes provide shortcuts that keep reads fast while you scale.
Learning Goals
- Identify columns in the schema that benefit from indexing
- Create single-column and composite indexes
- Understand how indexes impact queries and write performance
- Practice measuring index usage with
EXPLAIN
Where Indexes Help
Good candidates include:
- Columns used in
JOINconditions (student_id,course_id,dept_id) - Columns frequently searched (
course_code,email) - Columns used for sorting or filtering by range (
enrollment.semester,enrollment.grade)
Remember: every PRIMARY KEY automatically has an index; you only need to add extra ones when queries rely on other columns.
Creating Indexes
CREATE INDEX idx_enrollment_student
ON enrollment (student_id);
Now queries that fetch a student's schedule avoid scanning the entire enrollment table:
SELECT e.semester, c.course_code, c.course_title
FROM enrollment AS e
JOIN course AS c ON c.course_id = e.course_id
WHERE e.student_id = 3;
Composite Index
Composite indexes speed up queries that filter on multiple columns in the same order as the index definition.
CREATE UNIQUE INDEX idx_enrollment_student_course_semester
ON enrollment (student_id, course_id, semester);
SQLite already enforces uniqueness through the constraint in our DDL, but adding an explicit index in engines that do not automatically index unique constraints can help.
Covering Range Queries
CREATE INDEX idx_enrollment_semester
ON enrollment (semester);
SELECT semester, COUNT(*) AS total
FROM enrollment
GROUP BY semester
ORDER BY semester DESC;
Measuring Impact with EXPLAIN
Use EXPLAIN (SQLite) or EXPLAIN ANALYZE (PostgreSQL) to see whether the optimizer uses your index.
EXPLAIN QUERY PLAN
SELECT *
FROM enrollment
WHERE student_id = 5 AND semester = 'Spring 2025';
Look for “SEARCH TABLE enrollment USING INDEX …” in the output.
When Not to Index
- Columns with very few distinct values (
grade, which is mostlyNULL,A,B, etc.) rarely benefit. - Tables that change constantly might suffer because each insert/update/delete must update every index.
- Avoid redundant indexes (e.g., both
(student_id)and(student_id, course_id)when you only query onstudent_id).
Maintenance Tips
- Review indexes alongside query patterns; remove unused ones to cut write overhead.
- After bulk imports, some databases need statistics refreshed (
ANALYZE TABLEorVACUUM ANALYZE). - Document why each index exists so future maintainers know when it’s safe to drop.
Summary
- Indexes speed up read-heavy workloads by avoiding full table scans.
- Target join keys, lookup columns, and ordering columns.
- Composite indexes matter when queries filter on multiple fields in sequence.
- Monitor performance with
EXPLAINand keep only the indexes you need.
Quiz
Show quiz
-
Which column is the best candidate for an index if you often query
SELECT * FROM course WHERE course_code = ??
A)course_title
B)course_code
C)credits
D)dept_id -
What is a downside of creating too many indexes on
enrollment?
A) Queries get slower
B) Inserts and updates must maintain each index, slowing writes
C) Foreign keys stop working
D) Semester values become less accurate -
How can you verify that a query uses
idx_enrollment_student?
A) Check the database logs
B) RunPRAGMA table_info(enrollment)
C) RunEXPLAIN QUERY PLANon the query
D) It is automatic; no verification is needed -
True or False: An index on
(student_id, course_id)can also speed up queries that filter only oncourse_id.
A) True
B) False
Answers
- B
- B
- C
- B