# Practical SQL Query Optimization for .NET Backend Engineers
Tối ưu query không nên bắt đầu bằng “thêm index”. Trước tiên cần xem query có được viết theo cách SQL Server dễ tối ưu hay không.
## SARGability
Không tốt:
“`sql
WHERE YEAR(CreatedAt) = 2026
“`
Tốt hơn:
“`sql
WHERE CreatedAt >= ‘2026-01-01’
AND CreatedAt < '2027-01-01'
```
Khi function được áp trực tiếp lên indexed column, SQL Server có thể khó sử dụng index hiệu quả.
Một ví dụ khác:
```sql
WHERE LOWER(Name) = 'abc'
```
cũng có thể gây vấn đề tương tự.
## LIKE với wildcard đầu
```sql
WHERE Name LIKE '%abc%'
```
thường không tận dụng B-tree index tốt.
## Tránh SELECT *
Không tốt:
```sql
SELECT *
FROM Events;
```
Tốt hơn:
```sql
SELECT Id, Name, EndTime
FROM Events;
```
Lợi ích:
- ít IO
- ít network
- ít memory
- dễ tạo covering index
## Offset Pagination
```sql
ORDER BY CreatedAt DESC
OFFSET 100000 ROWS
FETCH NEXT 20 ROWS ONLY;
```
Offset lớn có thể ngày càng chậm.
## Keyset Pagination
```sql
WHERE CreatedAt < @lastCreatedAt
ORDER BY CreatedAt DESC
FETCH NEXT 20 ROWS ONLY;
```
Thường scale tốt hơn vì database seek từ một boundary đã biết.
## N+1 Problem
```text
SELECT Users
```
Sau đó:
```text
for each user
SELECT Orders
```
100 users có thể tạo 101 queries.
Giải pháp có thể là:
- projection
- join
- controlled Include
- batch query
## Interview questions
### What is a sargable predicate?
> A sargable predicate allows the database engine to efficiently use an index to locate rows instead of applying a transformation to every row.
### Offset vs cursor pagination?
> Offset pagination is simple but becomes expensive at large offsets. Cursor or keyset pagination scales better because it seeks from a known key instead of skipping many rows.
## Key takeaways
Query optimization nên đi theo flow:
“`text
Query shape
↓
Indexes
↓
Execution plan
↓
Actual workload
“`
**Next:** Part 7 — EF Core Performance