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

SQL Server Indexes Intermediate 1–2 Yrs2–3 Yrs3–5 Yrs Conceptual 2 min read

Quick Answer

A clustered index determines the physical order of the rows in the table — the leaf level of the index is the table data — so there can be only one. A non-clustered index is a separate structure; its leaf level holds the index key plus a pointer (the clustered key, or a RID for a heap) back to the row, and a table can have many.

The clustered index is the table — its leaf level holds the actual rows in sorted order by the clustered key, so you only get one per table. A non-clustered index is a separate copy of just the key columns, sorted, with a pointer back to the row. You can have lots of them. The practical consequence is the key lookup: if a query uses a non-clustered index but needs a column that isn't in it, SQL Server has to jump back to the clustered index for every matching row, and that gets expensive. You avoid it by including the needed columns in the index so it “covers” the query. Also, because the clustered key is stored inside every non-clustered index as the locator, you want it narrow and increasing — an int identity, not a random GUID.

ClusteredNon-clustered
How many per tableOneUp to 999
Leaf level containsThe actual data rows, sorted by the keyIndex key + row locator
Affects physical orderYesNo
Extra lookup?No — you're already at the dataSometimes a key lookup to fetch non-indexed columns
StorageNo extra copy of dataSeparate structure, extra space

Key points:

  • A table with a clustered index is a clustered table; without one it's a heap. The primary key creates a clustered index by default (you can override).
  • A non-clustered index seek that needs columns it doesn't contain does a key lookup into the clustered index for each row — fine for a few rows, expensive for many. Fix by INCLUDE-ing those columns (a covering index).
  • The clustered key is duplicated into every non-clustered index as the locator, so a narrow, static, ever-increasing clustered key (like an int/bigint identity) is preferred; a wide or random key (like a random GUID) bloats every index and causes page splits.

SQL — clustered PK + covering non-clustered
CREATE TABLE dbo.Orders
(
    OrderId    INT IDENTITY PRIMARY KEY,   -- clustered by default: narrow, increasing
    CustomerId INT NOT NULL,
    OrderDate  DATETIME2 NOT NULL,
    Total      DECIMAL(12,2) NOT NULL,
    Status     TINYINT NOT NULL
);

-- avoids a key lookup for: SELECT CustomerId, Total FROM Orders WHERE Status = 1
CREATE NONCLUSTERED INDEX IX_Orders_Status
    ON dbo.Orders (Status) INCLUDE (CustomerId, Total);

Practise the whole thread the way an interviewer walks it — each question builds on the last.

  1. What is an index in SQL Server?
  2. What is the difference between a clustered and a non-clustered index?You are here
  3. When should you create an index?
  4. Can indexes hurt performance?
  5. What is an execution plan in SQL Server?
  6. How do you optimise a slow SQL query?