Skip to content
Part IA Michaelmas Term

Join Complexity and Database Indexes

Brute force join

Given relations R(A,B)R(A, B) and S(B,C)S(B, C), the naive approach to compute RSR \bowtie S scans RR, and for each tuple in RR, scans all of SS. In the worst case this requires on the order of R×S|R| \times |S| steps:

TbruteRST_{\text{brute}} \propto |R| \cdot |S|

This is quadratic in the table sizes and becomes infeasible for large tables.

The common case

In practice, on each iteration over RR, there may be only a very small number of matching records in SS. If RR‘s BB is a foreign key referencing S(B)S(B), there is exactly one matching tuple. The brute force strategy still scans all of SS to find it.

Indexes

An index is a data structure that can greatly reduce the time needed to locate records matching a given key. With an index on S(B)S(B), the inner loop becomes a lookup on S-INDEX-ON-B(b):

TindexedRlogST_{\text{indexed}} \propto |R| \cdot \log |S|

This reduces the inner loop from S\propto |S| (linear scan) to logS\propto \log |S| (index lookup). For large tables, the difference is enormous.

SQL syntax

CREATE INDEX index_name ON S(B);
DROP INDEX index_name;

Index types and considerations

There are many types of database indexes (B-trees, hash indexes, bitmap indexes, GIN, GiST, and so on). The SQL standard does not define index creation; the syntax varies between implementations. Index creation is a physical design concern and may be handled by a specialist DBA team or by automated tools in modern systems.

The fundamental trade-off

OperationEffect of indexes
Read (SELECT)Faster (lookup instead of scan)
Write (INSERT, UPDATE, DELETE)Slower (index must be updated)

This is a fundamental database trade-off: every index speeds up queries that use it, but imposes a cost on every write operation. Choosing which indexes to create requires understanding the workload’s balance of reads and writes.

Underlying data structures

The Ia Algorithms course presents the data structures used to implement indexes:

  • Search trees (B-trees and variants): support range queries and ordered access.
  • Hash tables: provide O(1)O(1) average-case equality lookups but no range queries.

A database may maintain multiple indexes per table, each optimised for different query patterns.

Summary

  • Without indexes, RSR \bowtie S is RS\propto |R| \cdot |S|.
  • An index on the join column reduces the inner loop to logS\propto \log |S|.
  • Indexes speed reads but slow writes — a fundamental trade-off.
  • Underlying data structures: search trees, hash tables.