clustered vs non clustered index: SQL Server Differences and When to Use Each

Quick Answer
In SQL Server, clustered vs non clustered index describes two ways to access table data. A clustered index stores the actual table rows at its leaf level. A nonclustered index stores separate entries with keys and row locators. A table can have one clustered index and many nonclustered indexes. The better choice depends on your queries and workload.
Key Takeaways
The best index depends on how your application reads and changes data. These seven facts will help you make a sound choice before adding an index.
- A clustered index stores the table's actual rows at its leaf level, organized by the clustered key.
- A nonclustered index provides a separate path to rows and can hold extra columns needed by a query.
- A SQL Server table supports one clustered index and up to 999 nonclustered indexes, subject to engine limits.
- A primary key does not have to be clustered, and both index types can enforce unique values.
- A covering nonclustered index can avoid extra row lookups when it holds every column the query needs.
- An index scan can cost less than repeated seeks and lookups when a query returns many rows.
- Actual execution plans, logical reads, and write costs offer better evidence than the index type alone.
Start with the queries your system runs most often. Then check which access path serves those queries at the lowest overall cost. An index that helps one SELECT statement may still slow down frequent writes.
clustered vs non clustered index: The Core Differences
The main difference lies in the leaf level of each index. A clustered index holds the actual data rows there. A nonclustered index has its own structure, which points to rows or contains enough values to answer a query itself.
Both use a B+ tree for SQL Server rowstore indexing. The tree lets the database search through key values without always reading every row. Microsoft's clustered and nonclustered index documentation explains how these structures work.
Here is a direct comparison for standard SQL Server disk-based rowstore tables.
| Feature | Clustered index | Nonclustered index |
|---|---|---|
| Leaf-level data | Contains the actual table rows. | Contains index entries and row locators. |
| Table organization | Organizes the table by its clustered key. | Creates a separate index structure. |
| Number per table | Only one is allowed. | Up to 999 may be supported. |
| Row location | Rows are part of the clustered index. | Locators identify heap rows or clustered keys. |
| Unique key required | No, unless a constraint needs one. | No, unless declared unique. |
| Primary key support | Can enforce a primary key. | Can also enforce a primary key. |
| Typical use | Main row access and key-range queries. | Searches on other columns and covering queries. |
| Write overhead | Maintained as the table changes. | Each extra index adds maintenance work. |
| Always faster? | No. Query cost determines the result. | No. Query cost determines the result. |
One clustered index is enough to define the table's rowstore organization. Extra nonclustered indexes offer other ways to find the same data. That is useful when an application searches by several different fields.
The documented limit of 999 nonclustered indexes is not a target. Most tables need far fewer. Each extra structure consumes space and must be kept up to date when data changes.
Another distinction matters: clustered-key order does not guarantee the order of query results. Use an ORDER BY clause when your application needs a defined output order.
How SQL Server Stores and Finds Indexed Rows
SQL Server uses index trees to reach matching rows efficiently. Each tree has upper levels that guide the search. The leaf level holds either complete rows or index entries, based on the index type.
This design affects the work done after a matching key is found. Sometimes the index already has everything the query needs. In other cases, SQL Server must fetch data from another structure. Those extra reads can change the cost of a query.
Clustered leaf pages contain the table rows
Imagine an Orders table with OrderID as its clustered key. SQL Server keeps the table rows in the leaf level of that clustered index. An equality search for one OrderID can follow the tree to the matching row.
The upper levels hold information that helps the engine choose the right path. At the leaf level, SQL Server reaches the full row, not just a separate pointer entry. This can work well for queries that look up individual orders by their key.
A clustered index can also help with key-range access. For example, a report may ask for orders whose OrderID falls within a given range. Rows with nearby key values can be reached through the ordered leaf structure.
Not every query uses a seek. If a report needs most of the rows, scanning the clustered index may cost less than many separate lookups. The optimizer weighs possible access methods before choosing a plan.
A table with no clustered index is called a heap. Heap rows are stored without a clustered-key-based table structure. Heaps can still have nonclustered indexes.
Nonclustered entries lead to rows or cover the query
Now imagine that staff often search for orders by CustomerID. A clustered index on OrderID does not give the same direct access path for that search.
A nonclustered index on CustomerID provides another route. Its entries hold the indexed key and a way to find the row. In a heap, this locator is a row identifier. In a clustered table, it is based on the clustered key.
Suppose the query also needs an Amount value. If that value is absent from the nonclustered index, SQL Server may need an extra lookup to fetch it.
A covering index solves that problem for a particular query. It contains all the columns needed for filtering and returning results. SQL Server can then answer the query using that index alone when the optimizer selects it.
This is one reason a well-designed nonclustered index can beat a clustered-index access path for a given query. The separate index may be smaller and require fewer page reads.
Microsoft's SQL Server index architecture and design guide covers row locators, key choice, and the costs of maintaining these structures.
Choose the Right Index for Seven Common Query Patterns
Choose an index for the work your application does, not for the name of the index type. A query that returns one row has different needs from a report that reads half a table.
The matrix below gives a practical starting point. Each row links a common workload to a possible design and a way to check it. These are design choices to test, not measured winners.
| Query pattern | Reasonable starting choice | Main trade-off | What to check |
|---|---|---|---|
| Find one order by its primary key. | A narrow clustered OrderID key may fit. | Key design affects other indexes. | Seek choice and logical reads. |
| Find a few rows by CustomerID. | Add a nonclustered CustomerID index. | Missing columns may need lookups. | Selectivity and lookup count. |
| Return Amount and OrderDate for one customer. | Consider a covering nonclustered index. | Included columns add size and write cost. | Coverage and actual reads. |
| Read a few fields from a wide table. | Test a narrow nonclustered access path. | Many matching rows may change the result. | Pages read and returned rows. |
| Read a range of clustered-key values. | Test clustered index range access. | Broad ranges may favor a scan. | Range size and plan operators. |
| Insert and update rows very often. | Keep only useful supporting indexes. | Each extra index needs maintenance. | Write latency and total workload cost. |
| Return a large share of the table. | Allow the optimizer to consider scans. | Repeated lookups may cost more. | Actual I/O and elapsed time. |
The biggest design choice often concerns coverage. An index on CustomerID may locate the right orders quickly. But if the query needs several other columns, fetching each full row can add substantial work.
Adding selected columns to the index may reduce those reads. Yet a wider index consumes more storage and must be maintained. The gain from reads has to justify the cost of writes.
The table also shows why a seek is not a prize by itself. A seek that produces thousands of lookups may do more work than one scan. Look at the full execution plan and the resources used.
Pick a clustered key that suits the table
A clustered key affects far more than one query. It also forms part of row-location information for nonclustered indexes on a clustered table.
Microsoft generally favors keys that are narrow, stable, unique, and often increasing. A narrow key can keep supporting indexes smaller. A stable key avoids the cost of changing the row's clustered-key value.
For many order tables, an integer OrderID is a sensible candidate. But workload details still matter. Sequential inserts can create contention at the last page under heavy concurrent writes. That risk deserves testing in systems with high insert rates.
Add nonclustered indexes for repeated access needs
A nonclustered index is most useful when it serves a query that runs often enough to justify the extra structure. Start with the columns used for filtering and joining. Then consider the columns returned by the query.
A column with many distinct values can make an effective search key for selective predicates. Still, data distribution matters more than a simple distinct-count rule. A search returning most of the table may gain little from a narrow index.
Good index design is a balance across the whole workload. Speeding up one report is not a win if it makes a busy order-entry system much slower.
Create Clustered and Nonclustered Indexes in SQL Server
You can define a clustered primary key and then add a nonclustered index for another query pattern. The sample below uses an Orders-style table. It is intended for a test database, not a live production table.
The code uses ordinary T-SQL syntax. Microsoft's CREATE INDEX reference documents the available options and version-specific limits.
Define a clustered primary key
First, create a table with a clustered OrderID key. The declaration makes the intended table organization explicit.
``sql
CREATE TABLE dbo.IndexDemo (
OrderID int NOT NULL,
CustomerID int NOT NULL,
OrderDate date NOT NULL,
Amount decimal(12,2) NOT NULL,
CONSTRAINT PK_IndexDemo
PRIMARY KEY CLUSTERED (OrderID)
);
``
The primary key prevents duplicate OrderID values. The CLUSTERED keyword tells SQL Server to use that key for the table's clustered rowstore index.
A primary key does not have to be clustered. SQL Server can enforce it through a unique nonclustered index. Microsoft's clustered index creation guide explains the relevant setup choices.
Build a covering nonclustered index
Next, suppose a customer-service screen shows the date and amount of each order for one customer. Create an index designed for that access pattern.
``sql
CREATE NONCLUSTERED INDEX IX_IndexDemo_CustomerDate
ON dbo.IndexDemo (CustomerID, OrderDate)
INCLUDE (Amount);
``
CustomerID is the leading key. OrderDate is the next key. Amount is stored as an included, nonkey value at the leaf level.
Now run the following query after adding suitable sample rows.
``sql
SELECT OrderDate, Amount
FROM dbo.IndexDemo
WHERE CustomerID = 1001;
``
This index contains all columns needed by that SELECT statement. It is therefore a candidate covering index. SQL Server may answer the query without fetching the full rows from the clustered index.
The INCLUDE clause helps avoid making every selected field part of the search key. Microsoft's included-column index guide explains this design.
For applicable newer SQL Server nonclustered rowstore indexes, Microsoft documents up to 32 key columns and a 1,700-byte key-size limit. Included columns are not counted as key columns for those limits. Older versions may have lower limits.
Do not add every table column to INCLUDE by default. A very wide index can become expensive to store and update. Also, the optimizer is free to choose a different access plan if it estimates a lower cost.
Test Whether the Index Actually Helps
Test index value with actual query results and resource use. A new index is not successful merely because SQL Server accepts the CREATE INDEX statement. It must make useful work cheaper without imposing excessive costs elsewhere.
A fair test needs representative data and a query your application truly runs. Very small sample tables often lead to scans, even when a suitable index exists. That is not necessarily a problem with the index.
Read actual execution plans and logical I/O
In SQL Server Management Studio, enable Include Actual Execution Plan before running the query. Microsoft's actual execution plan instructions explain how to collect this information.
An actual plan can show which access method SQL Server used. Look for Index Seek, Clustered Index Scan, Index Scan, and Key Lookup operators. Also inspect actual row counts and differences from estimates.
To check page reads, turn on SQL Server's I/O statistics for the session.
```sql SET STATISTICS IO ON;
SELECT OrderDate, Amount FROM dbo.IndexDemo WHERE CustomerID = 1001;
SET STATISTICS IO OFF; ```
STATISTICS IO reports logical reads and other I/O details. Logical reads count pages read from the buffer pool. They are not the same as physical disk reads.
A lower logical-read count can be a useful sign. But the full workload still matters. Read counts alone do not capture all CPU, memory, concurrency, or write effects.
An estimated plan is useful before executing a costly query. It does not provide actual runtime measurements because the statement was not run. Microsoft's estimated execution plan guidance clarifies this distinction.
Compare the candidate with the baseline
Start with the original table design. Capture the query's actual plan and resource use. Add the candidate index in a controlled test environment, then repeat the same query.
Keep important conditions similar. Use the same data, parameters, and result columns. Run the query more than once, since caching and other system activity may affect timing.
Next, check the cost of writes. An index may make the customer lookup faster while causing every order insert to update another B+ tree. Updates to indexed columns can also add work.
A good result is not simply a faster SELECT. It is a better trade-off for the application as a whole. A report-heavy system can justify an index that a write-heavy system would reject.
Confirm which indexes exist
SQL Server exposes index metadata through catalog views. The following query lists indexes on the example table.
``sql
SELECT
name,
type_desc,
is_unique,
is_primary_key
FROM sys.indexes
WHERE object_id = OBJECT_ID(N'dbo.IndexDemo');
``
The result can confirm whether an index is clustered, nonclustered, unique, or tied to a primary key. Microsoft's sys.indexes reference explains those fields.
For this example, the expected definitions include a clustered primary-key index and a separate nonclustered index. Metadata confirms the structures exist. It does not prove that the query benefits from them.
Avoid Five Common Index Design Mistakes
The most costly index errors often start with a simple assumption. A developer hears that an index is fast, adds several of them, and expects every query to improve. SQL Server must maintain each structure while choosing among possible access paths.
Here are five mistakes worth checking before a new index reaches production.
- Assuming clustered indexes are always faster. A covering nonclustered index may serve a selective query with fewer reads. Compare actual plans before judging.
- Choosing a very wide clustered key. Large key values can increase the size of supporting nonclustered indexes. Favor a suitable narrow, stable key when the workload allows.
- Creating an index for every query. Extra indexes add storage and write work. Prioritize recurring queries with meaningful costs.
- Treating primary keys as always clustered. Primary-key constraints enforce uniqueness. The supporting index can be clustered or nonclustered.
- Expecting clustered order to sort query output. Use ORDER BY when result order matters. Index organization alone is not an output-order promise.
The first two mistakes affect the table's basic design. Changing a clustered key later can be costly, especially on large tables with many supporting indexes. Spend more time on that choice than on a small, easy-to-replace secondary index.
The third mistake grows over time. Old reports may no longer run, but their indexes can remain. Periodic workload review helps find structures that impose cost without serving an important access need.
Finally, avoid assuming that a sequential key is always ideal. It may help insert patterns, but heavy concurrent inserts can create last-page contention. Measure that behavior before changing the key to solve a problem you may not have.
SQL Server and PostgreSQL Use Different Clustering Models
SQL Server clustered indexes and PostgreSQL's CLUSTER command do not mean the same thing. They both concern row organization, but they work differently.
In SQL Server, the clustered rowstore index is the table's ongoing indexed storage structure. Its leaf level contains the table rows. Updates and inserts are handled as part of maintaining that structure.
PostgreSQL uses CLUSTER to reorder an existing table based on an index. The operation is not a continuously maintained clustering scheme. Later inserts and updates can change the physical arrangement.
The official PostgreSQL 18 CLUSTER documentation states that clustering is a one-time operation. It also explains the need to repeat the work if the physical ordering becomes less useful over time.
This difference matters when reading database tutorials. A rule that fits SQL Server may not apply to PostgreSQL. Index limits, storage behavior, syntax, and maintenance methods depend on the engine.
For the design decisions in this article, use SQL Server's rowstore model. If your project uses PostgreSQL, review its own indexing and CLUSTER guidance before applying a similar plan.
Frequently Asked Questions
These questions cover the points that often cause confusion during SQL interviews and real database work. The answers apply to standard SQL Server rowstore indexes unless another engine is named.
1. Can a SQL Server table have multiple clustered indexes?
No. A table can have only one clustered index because that index defines its clustered rowstore organization. It can have many nonclustered indexes for other query patterns. A documented upper limit is 999 nonclustered indexes under applicable SQL Server conditions, but a sound design uses only the indexes it needs.
2. Is a primary key always a clustered index?
No. SQL Server often creates a clustered index for a primary key by default when the table has no clustered index. You can explicitly define a primary key as NONCLUSTERED. The primary-key constraint enforces data integrity, while the index type determines how SQL Server provides access to the key.
3. Can a nonclustered index be faster than a clustered index?
Yes. A nonclustered index may be smaller and better aligned with a query's filter. A covering index can also avoid fetching extra columns from the base table. Neither outcome is certain for every query. Check actual reads and the execution plan to see which access method works best.
4. Does an Index Seek always beat an Index Scan?
No. A seek is useful when SQL Server can narrow the search. But a seek followed by many row lookups may cost more than a scan. Scans are often reasonable when the query returns a large share of the table. Judge the complete plan, not one operator name.
5. Can a nonclustered index have duplicate values?
Yes. A nonclustered index does not have to be unique. For instance, many orders can share the same CustomerID. SQL Server can store repeated indexed values and still locate the matching rows. Add a unique constraint or unique index only when the data rules require unique values.
6. What happens if a table has no clustered index?
The table is a heap. It stores rows without a clustered index defining their logical key order. You can still create nonclustered indexes on a heap. Their row locators use row identifiers rather than clustered keys. Whether a heap is suitable depends on the workload and table design.
7. Do nonclustered indexes slow down INSERT and UPDATE statements?
They can. When a write changes indexed data, SQL Server must keep the affected index structures up to date. More indexes can add I/O, logging, and CPU work. The cost varies with the changed columns and workload. Compare read gains with write costs before keeping an index.
8. When should I use INCLUDE columns?
Use them when a common query needs extra columns that do not belong in the index search key. Those columns can help create a covering index. For example, a CustomerID search may include Amount for display. Limit included columns to those with a clear benefit, since they still consume space and add maintenance work.
The Practical Index Selection Rule
The best SQL Server index design starts with real queries. Choose a clustered key that fits the table's main access needs and stays stable as data grows. Then examine the filters, joins, and returned columns in your most important queries.
For frequent searches that the clustered key does not serve well, test a nonclustered index. Add INCLUDE columns only when they help cover a useful query. Compare actual execution plans and logical reads with the baseline.
Do not stop at faster reads. Review write costs and storage needs too. Keep an index when it improves the workload enough to justify its upkeep.
Database indexing is separate from search-engine indexing topics covered in the IndexNowFast blog. SQL Server index choices affect how a database finds its records. They do not control how Google discovers or lists web pages.
A reliable decision is based on the structure, the query, and measured behavior—not a claim that one index type always wins.