Interview Q&A / SQL & DBMS

AdvancedIn-depth4 min readUpdated 2 Oct 2026

What is the difference between a clustered and a non-clustered index?

SHORT ANSWER

A clustered index decides the physical order in which table rows are stored, so the table itself is the index and there can be only one. A non-clustered index is a separate structure holding the indexed values plus a pointer back to the row, and a table can have many.

Explain it simply

A telephone directory is sorted by surname. The data itself is in that order, so finding "Sharma" means flipping straight to the S pages, and all the Sharmas sit together. That is a clustered index. A book can only be physically sorted one way, so there is only one.

The index at the back of a textbook is different. It lists topics alphabetically with page numbers. You look up "Normalization", read "page 212", then turn to that page. That is a non-clustered index: a separate list that points to where the real content lives. A book can have several such indexes: by topic, by author name, by figure number.

Example

SQL Server syntax, where the difference is explicit:

sql
CREATE TABLE orders (
  order_id    int NOT NULL,
  customer_id int NOT NULL,
  order_date  date NOT NULL,
  amount      decimal(10, 2)
);

-- One clustered index: rows are stored in order_id order
CREATE CLUSTERED INDEX ix_orders_id ON orders (order_id);

-- Many non-clustered indexes: separate structures pointing back to rows
CREATE NONCLUSTERED INDEX ix_orders_customer ON orders (customer_id);
CREATE NONCLUSTERED INDEX ix_orders_date ON orders (order_date) INCLUDE (amount);

In SQL Server, a PRIMARY KEY creates a clustered index by default if the table does not have one already.

How it works

Clustered indexNon-clustered index
What it storesThe full rows, in key orderKey values plus a row locator
Number per tableOneMany
Lookup costFind key, data is right thereFind key, then fetch the row (an extra lookup) unless the index covers the query
Range queries on the keyVery fast, rows are adjacentCan be slow if many matching rows are spread out
Effect on insertsRows inserted in the middle can cause page splitsEach index adds write work

Both are usually B-tree structures. In a clustered index the leaf level holds the actual rows. In a non-clustered index the leaf level holds the key and a locator: the clustered key value if the table has a clustered index, or a physical row ID if it does not.

How common databases handle this:

  • MySQL InnoDB: every table is clustered on its primary key. If there is no primary key, InnoDB uses the first unique NOT NULL index, or creates a hidden row ID. Secondary indexes store the primary key value, so a big primary key makes every secondary index bigger.
  • SQL Server: you choose which index is clustered; a table without one is called a heap.
  • PostgreSQL: tables are always heaps and all indexes are separate structures, so in SQL Server terms every PostgreSQL index is non-clustered. The CLUSTER command reorders a table by an index once, but the order is not maintained for new rows.

Real-world use

  • Cluster an orders table on an increasing order_id or created_at, so new rows go at the end and "orders from last week" reads neighbouring pages.
  • Add non-clustered indexes on columns you filter by, such as customer_id or a phone number on a users table.
  • Use a covering index (INCLUDE columns) for a frequent query, so it never has to visit the table.

Common mistakes

  • Saying a table can have several clustered indexes. It has at most one, because rows can be stored in only one order.
  • Assuming the primary key and the clustered index are always the same thing. They often are by default, but in SQL Server you can cluster on a different column.
  • Choosing a random value, like a random UUID, as the clustered key. Inserts land all over the table and cause page splits and fragmentation.
  • Describing PostgreSQL indexes as clustered because of the CLUSTER command.

What to say in the interview

"A clustered index defines the physical order of the rows, so the leaf level of the index is the table itself, and a table can have only one. A non-clustered index is a separate B-tree containing the key and a pointer to the row, so lookups may need an extra step to fetch the row, but a table can have many. In SQL Server the primary key is clustered by default, and in MySQL InnoDB the table is always clustered on the primary key and secondary indexes store that key. PostgreSQL stores tables as heaps, so all its indexes behave like non-clustered ones. I pick a narrow, increasing clustered key to keep inserts cheap and secondary indexes small."

Follow-up questions

  • What is a covering index, and what is a key lookup?
  • Why is a narrow, increasing primary key preferred in InnoDB?
  • What is a page split?

Go deeper

Read these once the basics above feel easy.

When a non-clustered index is used in SQL Server and the query needs columns not in the index, each match triggers a key lookup into the clustered index. For a handful of rows this is cheap; for thousands it is often slower than scanning the clustered index, so the optimizer may ignore the non-clustered index entirely. Adding the needed columns with INCLUDE turns it into a covering index and removes the lookups. In PostgreSQL, the equivalent is an index-only scan, which also depends on the visibility map being up to date, since PostgreSQL must confirm that rows are visible without reading the heap.

#sql#indexes#dbms#performance#database-design

Related questions

Practise more SQL & DBMS questions

Test your recall with short answers, then return to the detailed explanations when you need context.

Open SQL & DBMS quick answers →

Get new questions like this by email

One short email when something new and useful lands. No spam, unsubscribe in one tap.

By subscribing you agree to the Privacy Policy.