Writing a working query is easy.
Writing a fast and scalable query is a different skill.
In Microsoft SQL Server, query performance depends on how efficiently SQL Server can read, filter, and join data.
This guide covers advanced techniques used in real production systems.
1๏ธโฃ Understand the Execution Plan First
Before optimizing anything:
โ Check Actual Execution Plan
โ Identify expensive operations
Look for:
โ Table Scan
โ Index Scan on large tables
โ Key Lookup
โ High cost operators
๐ Never optimize blindly.
2๏ธโฃ Reduce Data Early (Filtering Strategy)
Always filter data as early as possible.
โ Bad
SELECT *
FROM Orders
WHERE YEAR(OrderDate) = 2025;
โ Good
SELECT *
FROM Orders
WHERE OrderDate >= '2025-01-01'
AND OrderDate < '2026-01-01';
โ Uses index
โ Reduces rows early
3๏ธโฃ Avoid SELECT *
Selecting unnecessary columns increases IO.
โ Bad
SELECT *
FROM Orders;
โ Good
SELECT OrderId, Amount
FROM Orders;
โ Faster
โ Less memory usage
4๏ธโฃ Optimize Joins Properly
Joins are one of the biggest performance factors.
Best Practices
โ Index join columns
โ Use correct join type
โ Avoid unnecessary joins
Example Optimization
CREATE INDEX IX_Orders_CustomerId
ON Orders(CustomerId);
5๏ธโฃ Eliminate Key Lookups
Key lookup = extra read operation.
Solution โ Covering Index
CREATE INDEX IX_Orders_UserId
ON Orders(UserId)
INCLUDE (OrderId, Amount);
โ Eliminates lookup
โ Improves performance
6๏ธโฃ Use EXISTS Instead of IN (for Large Data)
โ IN (slower for large data)
SELECT *
FROM Orders
WHERE UserId IN (SELECT UserId FROM Users);
โ EXISTS
SELECT *
FROM Orders O
WHERE EXISTS (
SELECT 1
FROM Users U
WHERE U.UserId = O.UserId
);
โ Better for large datasets
7๏ธโฃ Avoid Functions on Indexed Columns
โ Bad
WHERE YEAR(OrderDate) = 2024;
โ Good
WHERE OrderDate BETWEEN '2024-01-01' AND '2024-12-31';
๐ Functions prevent index usage.
8๏ธโฃ Use Proper Data Types
Wrong data types cause implicit conversions.
โ Bad
WHERE UserId = '100';
โ Good
WHERE UserId = 100;
โ Enables index usage
9๏ธโฃ Use Temp Tables for Complex Queries
Break complex queries into steps.
SELECT *
INTO #TempOrders
FROM Orders
WHERE OrderDate > '2025-01-01';
Then process further.
โ Improves readability
โ Helps optimizer
๐ Use Window Functions Efficiently
Window functions are powerful but expensive.
Example:
SELECT
UserId,
ROW_NUMBER() OVER (PARTITION BY UserId ORDER BY OrderDate) AS RowNum
FROM Orders;
โ Use only when necessary
โ Combine with indexes
1๏ธโฃ1๏ธโฃ Avoid Cursors (Use Set-Based Logic)
โ Cursor (slow)
DECLARE cursor_example CURSOR FOR
SELECT UserId FROM Users;
โ Set-based
UPDATE Users
SET Status = 'Active'
WHERE LastLogin > GETDATE() - 30;
โ Much faster
โ Better scalability
1๏ธโฃ2๏ธโฃ Handle Parameter Sniffing
Use techniques like:
โ Local variables
โ OPTION (RECOMPILE)
OPTION (RECOMPILE);
๐ Useful for variable data patterns.
1๏ธโฃ3๏ธโฃ Optimize Aggregations
โ Bad
SELECT SUM(Amount)
FROM Orders;
(Without index)
โ Better
CREATE INDEX IX_Orders_Amount ON Orders(Amount);
โ Speeds up aggregation
1๏ธโฃ4๏ธโฃ Real Production Example
โ Problem
Query taking 20 seconds
๐ Issue
- Table scan
- Key lookup
- Missing index
โ Fix
CREATE INDEX IX_Orders_UserId
ON Orders(UserId)
INCLUDE (Amount, OrderDate);
Result
20 sec โ 80 ms
1๏ธโฃ5๏ธโฃ Optimization Checklist
Before finalizing any query:
โ Check execution plan
โ Avoid SELECT *
โ Use proper indexes
โ Remove unnecessary joins
โ Avoid functions in WHERE
โ Validate data types
โ๏ธ Conclusion
Advanced query optimization is about:
โ Understanding how SQL Server works
โ Reducing unnecessary work
โ Helping the optimizer choose better plans
Mastering these techniques makes you:
โ Faster at debugging
โ Better at performance tuning
โ Highly valuable in production systems
