In this lesson, you will learn how to strike the right balance between fast read performance and efficient write operations when indexing foreign key columns.
The Balancing Act
When you define a FOREIGN KEY in SQL, the database ensures that every value in that column exists in the parent table. While this is great for data integrity, the database does not automatically create an index for you. Without an index, joining tables or performing cascading deletes can force the engine to perform a slow "full table scan" to verify constraints.
However, adding an index to every single foreign key is not always the best move. Every index you create incurs a "write penalty." Whenever you INSERT, UPDATE, or DELETE a row, the database must also update the corresponding index structures. If you have a high-traffic table with frequent modifications, too many indexes can significantly slow down these write operations.
When to Index vs. When to Skip
- Always Index for Performance: If your application frequently joins the child table with the parent table (e.g.,
SELECT * FROM Orders JOIN Customers ON Orders.customer_id = Customers.id), you should absolutely indexcustomer_id. The read performance gain far outweighs the minor write cost. - Index for Cascading Operations: If you have
ON DELETE CASCADEorON DELETE SET NULLconstraints, the database must locate all child records when a parent record is deleted. An index on the foreign key column allows the database to find those children instantly. Without an index, the engine might scan the entire table just to find a handful of related rows. - Consider Skipping for Static Data: If you have a table that is almost exclusively written to (a log table, for instance) and you rarely query it by the foreign key, you might choose to omit the index to keep insert speeds as high as possible.
Example
Imagine an Orders table linked to Customers:
CREATE INDEX idx_orders_customer_id ON Orders(customer_id);
By indexing customer_id, your joins become lightning-fast. The database performs an index seek rather than a scan. You’ve accepted a tiny overhead on each INSERT to ensure that every SELECT remains performant as your table grows.
Key Takeaway: Prioritize indexing foreign keys used in frequent joins or those subject to cascading deletes, but monitor your write-heavy tables to ensure your indexing strategy doesn't become a bottleneck for updates.