Introduction
When an application is small, every SQL query feels fast. But as data grows into thousands, millions, or even billions of rows, performance problems begin appearing. A SELECT query that took 20 milliseconds earlier may suddenly take 5 seconds or more. Developers often assume something is wrong with code or infrastructure, but the real bottleneck is frequently the absence (or misuse) of indexes.
Indexes are one of the most important performance optimization features in SQL Server. They allow the database engine to find rows faster, just like an index in a book helps you quickly locate a topic instead of reading every page.
This article explains indexes from a practical angle:
What indexes are
How they work internally
When to use them
When not to use them
Real-world examples and measurable impact
Real-World Context
Consider a ServiceRecord table storing service history for a large automobile service chain:
CREATE TABLE ServiceRecord (
ServiceId INT PRIMARY KEY,
CarId INT,
ServiceDate DATE,
Cost DECIMAL(10,2),
Description NVARCHAR(500)
);
After 20 customers, everything is fast.
After 200,000 records, queries start slowing.
After 2 million records, basic SELECT queries may become painfully slow without indexing.
What Is an Index?
An index is a data structure that SQL Server uses to quickly locate rows without scanning the entire table.
Example
Query without an index:
SELECT * FROM ServiceRecord
WHERE CarId = 101;
SQL Server must scan the whole table row by row. This is called a Table Scan.
Query with an index on CarId:
CREATE INDEX IX_ServiceRecord_CarId ON ServiceRecord(CarId);
Now SQL Server performs an Index Seek, which is significantly faster.
How Indexes Work Internally
SQL Server primarily uses a B-Tree structure.
Root Level
↓
Intermediate Nodes
↓
Leaf Level (actual row pointers)Instead of searching every record, SQL follows this sorted tree structure, making lookups significantly faster.
Performance Comparison
| Operation Type | With Index | Without Index |
|---|---|---|
| Table scan | Yes | Yes |
| Index seek | Yes | No |
| Lookup time | Fast (logarithmic) | Slow (linear) |
| Useful for large tables | Yes | No |
Types of Indexes in SQL Server
1. Clustered Index
A clustered index defines how data is physically stored in the table.
A table can have only one clustered index.
By default, the Primary Key becomes the clustered index.
Example
CREATE CLUSTERED INDEX IX_ServiceRecord_ServiceId
ON ServiceRecord(ServiceId);
Clustered indexes are ideal for:
Primary keys
Columns used in sorting and range searches (
BETWEEN,<,>, ORDER BY)
2. Non-Clustered Index
A non-clustered index contains a copy of the indexed column and a pointer to the actual data.
Example
CREATE NONCLUSTERED INDEX IX_ServiceRecord_ServiceDate
ON ServiceRecord(ServiceDate);
Use non-clustered indexes for:
Frequently searched columns
JOIN conditions
WHERE filters
3. Composite Index
Indexes on multiple columns.
Example
CREATE INDEX IX_ServiceRecord_CarId_ServiceDate
ON ServiceRecord(CarId, ServiceDate);
Useful when queries combine both fields.
4. Included Column Index
Adds non-key columns to improve coverage and avoid extra lookups.
Example
CREATE INDEX IX_ServiceRecord_CarId
ON ServiceRecord(CarId)
INCLUDE (Cost, ServiceDate);

Join the conversation! Your thoughts help the community grow.