Clustered Index
Clustered Index
The index that IS the table's physical order
A clustered index is special: it determines the physical storage order of the table's rows on disk. Rather than being a separate structure that merely points to rows stored elsewhere, the table's data itself is physically arranged according to the clustered index's key.
Imagine students has a clustered index on id. This means the actual rows are stored on disk sorted by id — row with id=1 physically precedes id=2, which precedes id=3, and so on. When you query WHERE id = 500000, the engine can navigate the B+ Tree structure of the clustered index and land directly on the physical page containing that row's actual data — no extra pointer-following step needed, because the leaf level of a clustered index is the table data itself.
The "at most one" rule
Because a clustered index physically reorders the table's rows, and rows can only be arranged in one physical sequence at a time, a table can have at most one clustered index. You cannot simultaneously store students physically sorted by both id and by gpa — you have to pick one ordering (or none, leaving the table as an unordered "heap").
In practice, the primary key is very often chosen as the clustered index, since primary-key lookups and joins are extremely common and benefit the most from this direct, no-extra-step access.
Why it's fast
Because the clustered index's leaves store the actual row data (not just a pointer to it), a lookup or range scan via the clustered key touches only the index structure — there's no second "hop" to a separate row storage location. This makes clustered-index range scans (e.g., WHERE id BETWEEN 1000 AND 2000) especially efficient, since the matching rows are also physically adjacent on disk.
Edge cases
- If a table has no explicit clustered index, most engines still store rows in some physical order — often insertion order in an unordered "heap," or automatically clustered by a hidden row identifier (behavior varies by engine, e.g., MySQL's InnoDB clusters by primary key by default, while some engines default to a heap).
- Choosing a clustered key that changes frequently (like a
gpathat gets updated often) is problematic, since updating the key can require physically moving the row to maintain sort order — an expensive operation. A stable, rarely-changing key (like an auto-incrementingid) is a much better clustered-index choice. - Inserting rows with non-sequential clustered-key values (e.g., random UUIDs as a clustered primary key) can cause frequent, expensive page reordering — a well-known real-world performance pitfall.
Interview-style Q&A
Q: Why can a table have only one clustered index? A: Because the clustered index defines the physical row order on disk, and rows can physically exist in only one order at a time.
Q: Why is a rarely-changing key a better choice for a clustered index than a frequently-updated one? A: Because updating a clustered key value can force the engine to physically relocate the row to preserve sort order — an expensive operation compared to updating a non-key column.
Key takeaway: a clustered index isn't a separate lookup structure pointing elsewhere — it IS the table's row storage, arranged in key order, which is why there can only ever be one per table.