Skip to content

Query Optimization Strategies: Tuyệt kỹ

Dưới đây là những kỹ thuật tối ưu hóa thực chiếnh mà bạn có thể áp dụng ngay để tăng tốc hệ thống.

1. Vấn đề N+1 Query (The Silent Killer)

Đây là lỗi phổ biến nhất khi dùng ORM (như Hibernate, Entity Framework, Laravel Eloquent).

Tình huống: Bạn muốn lấy danh sách Users và Orders của họ.

python
users = User.objects.all() # 1 Query lấy Users
for user in users:
    print(user.orders)     # N Query lấy Orders cho từng User

Nếu có 1000 users, bạn sẽ chạy 1 + 1000 = 1001 query. Database sẽ bị "ngập lụt".

Giải pháp (Eager Loading): Dùng JOIN ngay từ đầu để lấy dữ liệu trong 1 query duy nhất.

sql
-- ORM sẽ sinh ra câu này
SELECT * FROM users
LEFT JOIN orders ON users.id = orders.user_id;

2. Tối ưu hóa điều kiện OR

Database thường rất dở trong việc dùng Index cho điều kiện OR.

Query chậm:

sql
SELECT * FROM users WHERE email = 'abc@gmail.com' OR phone = '0901234567';
-- Thường sẽ dẫn đến Full Table Scan nếu Database không thông minh.

Giải pháp (UNION ALL): Tách thành 2 query nhỏ dùng Index riêng biệt và gộp lại.

sql
(SELECT * FROM users WHERE email = 'abc@gmail.com')
UNION ALL
(SELECT * FROM users WHERE phone = '0901234567');

Mỗi query con sẽ dùng Index của emailphone cực nhanh.

3. Chỉ lấy những gì bạn cần (Select Fields)

Như đã nói ở bài Basic, đừng bao giờ SELECT *. Ngoài ra, hãy cẩn thận với cột kiểu TEXT, JSON lớn. Nếu không cần hiển thị nội dung bài viết, đừng SELECT content. Việc chuyển dữ liệu lớn qua mạng (Network I/O) thường chậm hơn bạn nghĩ.

4. Đừng tính toán trong Database nếu không cần thiết

Database được thiết kế để lưu trữ và truy xuất, không phải để tính toán phức tạp.

Tệ:

sql
-- Bắt Database tính MD5 cho 1 triệu dòng
SELECT id, MD5(email) FROM users;

Tốt: Lấy email ra và để Application Server (Node.js, Go, Java) tính MD5. App Server scale (mở rộng) dễ hơn và rẻ hơn Database Server rất nhiều.

5. Bulk Insert / Bulk Update

Đừng bao giờ insert dữ liệu trong vòng lặp for.

Sai (Chậm gấp 100 lần):

python
for item in items:
    db.insert(item) -- Mỗi lần 1 kết nối, 1 transaction

Đúng:

sql
INSERT INTO table (col1, col2) VALUES 
(1, 'a'), 
(2, 'b'), 
(3, 'c'); -- 1 Query duy nhất