Introduction
SQL Server is powerful, but even experienced developers sometimes write queries that perform poorly in real environments. What works fine with 5,000 rows may fail when the table grows to 5 million or when concurrency increases.
Slow queries affect:
Page load times
Reporting dashboards
Queue-based background processing
High-volume transactional systems
Performance degradation increases server CPU, memory, and IO load, which directly increases infrastructure cost.
The good news is most slow queries can be fixed with a few well-understood optimization techniques.
This article explains how to diagnose, analyze, and fix slow queries based on real-world scenarios.
Case Study: Inventory Dashboard Query
A developer wrote the following query for an ERP stock dashboard:
SELECT *FROM Stockline s
JOIN Warehouse w ON s.WarehouseId = w.WarehouseId
WHERE s.PartNumber LIKE '%BRAKE%'AND s.Status = 'Active'ORDER BY CreatedDate DESC;
On day one, it ran in milliseconds. After one year, with 12 million stock records, it now takes:
18 seconds to run
70 percent CPU spike
Timeout in web application
Step 1: Use Execution Plans
SQL Server can show how the query is executed.
Run:
SET SHOWPLAN_ALL ON;
Or in SSMS:
Query menu > Include Actual Execution Plan
Common indicators of problems:
| Indicator | Meaning |
|---|---|
| Table Scan | No useful index found |
| Key Lookup | Index exists but not covering |
| Hash Join | Large join operation |
| High Cost Operator | Needs optimization |
In our case, the execution plan shows:
Table Scan on
StocklineKey Lookup on Warehouse
Cost concentrated on LIKE search
Step 2: Check Indexes
Indexes dramatically improve speed by avoiding full table scans.
Create an index:
CREATE INDEX IX_Stockline_Status_PartNumber
ON Stockline (Status, PartNumber);
But partial search with %BRAKE% makes the index less useful.
Better pattern: avoid leading wildcard.
Instead of:
'%BRAKE%'Try:
'BRAKE%'If business requires substring searching, use:
Full-Text search
Search indexing engine
CREATE FULLTEXT INDEX ON Stockline(PartNumber)
KEY INDEX PK_Stockline;
Step 3: Avoid SELECT *
Selecting only required columns reduces:
IO reads
Memory use
Network transfer cost
Rewrite:
SELECT
s.StocklineId,
s.PartNumber,
s.CreatedDate,
w.WarehouseName
FROM Stockline s
JOIN Warehouse w ON s.WarehouseId = w.WarehouseId
WHERE s.PartNumber LIKE 'BRAKE%'AND s.Status = 'Active'ORDER BY s.CreatedDate DESC;
Step 4: Use Proper Filtering Order and Predicates
SQL Server uses sargable (Search ARGument Able) conditions, meaning they can utilize an index.
Bad (non-sargable):
WHERE YEAR(CreatedDate) = 2024Better:
WHERE CreatedDate BETWEEN '2024-01-01' AND '2024-12-31'Bad:
WHERE CONVERT(VARCHAR, PartNumber) = 'BRAKE100'Better:

Join the conversation! Your thoughts help the community grow.