THIẾT KẾ WEB XÂY DỰNG
Truy vấn MySQL bị chậm? Đây là cách giúp bạn tăng tốc x10 lần
❗ Vấn đề thường gặp – Câu truy vấn chậm:
Nhiều hệ thống MySQL gặp tình trạng truy vấn rất chậm dù chỉ cần lấy vài dòng dữ liệu (ví dụ: 6 sản phẩm nổi bật). Nguyên nhân phổ biến là vì câu truy vấn đang JOIN nhiều bảng lớn, sau đó mới ORDER BY và LIMIT, khiến MySQL phải xử lý hàng ngàn dòng trước rồi mới lọc ra vài dòng sau cùng. Điều này càng nghiêm trọng nếu bạn JOIN với các bảng VIEW
, không có index hỗ trợ, hoặc dùng các điều kiện như != ''
hoặc IS NOT NULL
trên cột văn bản. Nếu không tối ưu, truy vấn tưởng chừng đơn giản có thể tiêu tốn hàng giây – đủ làm chậm toàn trang web hoặc API.
Câu truy vấn chậm
Ví dụ điền hình query Mysql:
SELECT p.product_id, p.product_name, p.price, p.date_added, c.category_name, b.brand_name
FROM products AS p
JOIN categories AS c ON p.category_id = c.category_id
JOIN brands AS b ON p.brand_id = b.brand_id
JOIN product_flags AS f ON f.product_id = p.product_id
AND f.flag_type = "featured"
WHERE p.status = "active"
AND p.stock > 0
ORDER BY f.date_added
DESC LIMIT 6;
❌ Tại sao chậm?
-
Bảng
products
có hàng chục ngàn dòng. -
JOIN 3 bảng:
categories
,brands
,product_flags
. -
ORDER BY f.date_added DESC LIMIT 6
xảy ra sau khi JOIN, tức JOIN xong hàng ngàn dòng mới sắp xếp → rất tốn tài nguyên.
✅ Hướng giải quyết: Truy vấn tối ưu

Chiến lược: Lấy danh sách
product_id
nổi bậtLIMIT 6
trước, rồi mới JOIN thêm dữ liệu chi tiết.
✅ Truy vấn tối ưu:
SELECT p.product_id, p.product_name, p.price, p.date_added, c.category_name, b.brand_name
FROM (
SELECT f.product_id
FROM product_flags AS f
JOIN products AS p ON f.product_id = p.product_id
WHERE f.flag_type = "featured"
AND p.status = "active"
AND p.stock > 0
ORDER BY f.date_added DESC
LIMIT 6
) AS top
JOIN products AS p ON p.product_id = top.product_id
JOIN categories AS c ON p.category_id = c.category_id
JOIN brands AS b ON p.brand_id = b.brand_id;
Kết quả:
So sánh | Truy vấn gốc | Truy vấn tối ưu |
---|---|---|
JOIN trên | Hàng ngàn dòng | Chỉ 6 dòng |
Chi phí ORDER BY |
Cực cao | Rất nhẹ |
Tốc độ | Chậm | Rất nhanh ⚡ |
Index đề xuất:
Trên bảng product_flags
:
CREATE INDEX idx_flag_type_date ON product_flags(flag_type, date_added DESC, product_id);
Trên bảng products
:
CREATE INDEX idx_products_active ON products(status, stock, product_id);
✅ Tóm gọn:
Vấn đề gốc:
ORDER BY ... LIMIT
xảy ra sau JOIN → xử lý dữ liệu dư thừa
Giải pháp:
Tách bước
LIMIT
thành subquery nhỏ trước, rồi mới JOIN dữ liệu phụ
Nếu bạn đang làm PHP (CodeIgniter, Laravel…), bạn cũng có thể cache subquery đầu tiên (danh sách product_id
nổi bật) trong 5 phút, sau đó dùng lại để JOIN nhanh hơn.
Kỹ thuật với database MySQL có thể bạn quan tâm
- MySQL Truy Vấn Thống Kê
- Các Kỹ Thuật Tìm Kiếm Trong MySQL
- MySQL truy vấn nâng cao - Cách viết biểu thức bảng trong MySQL
- Truy vấn nâng cao MySQL
- Hàm thời gian trong MySQL
- Hướng dẫn cách Tạo View Xóa View trong MySQL
- Làm thế nào để thêm ràng buộc Not Null xóa ràng buộc trong MySQL
- Cách Thêm Một Cột Xóa Cột Thay Đổi Tên Cột Trong Bảng MySQL
- Cách tạo bảng xóa bảng đổi tên bảng trong MySQL