02/05/2026
Trong quá trình tối ưu query với Microsoft SQL Server, rất nhiều developer mắc một sai lầm phổ biến: tối ưu dựa trên cảm giác. Thêm index theo suy đoán, rewrite query theo kinh nghiệm cá nhân, nhưng không kiểm chứng SQL Server thực sự đang làm gì phía sau.
Ex*****on Plan (kế hoạch thực thi) chính là “bản đồ” cho bạn biết database engine đang truy cập dữ liệu ra sao, join kiểu gì, sort như thế nào và tốn tài nguyên ở đâu. Nếu không đọc Ex*****on Plan, việc tối ưu gần như là mò mẫm trong bóng tối.
Bài viết này sẽ giúp bạn hiểu đầy đủ cách đọc, phân tích và tối ưu dựa trên Ex*****on Plan – theo hướng thực chiến.
1. Ex*****on Plan là gì?
Ex*****on Plan là mô tả chi tiết cách SQL Server thực thi một câu lệnh T-SQL. Nó cho bạn biết:
SQL dùng Index Seek hay Table Scan?
Join bằng Nested Loop hay Hash Match?
Có Sort không?
Có Key Lookup không?
Estimated rows có khớp với Actual rows không?
Có hai loại:
Estimated Ex*****on Plan – kế hoạch ước lượng trước khi chạy.
Actual Ex*****on Plan – kế hoạch thực tế sau khi chạy (quan trọng hơn).
Trong SQL Server Management Studio, bạn bật Actual Ex*****on Plan bằng Ctrl + M.
2. Cách đọc Ex*****on Plan đúng cách
Nguyên tắc 1: Đọc từ phải sang trái
Ex*****on Plan chạy theo chiều từ phải qua trái. Operator ngoài cùng bên phải là nơi dữ liệu được truy xuất đầu tiên.
Nguyên tắc 2: Tìm operator có % cost cao nhất
Operator nào chiếm tỷ lệ cost cao thường là điểm nghẽn chính.
Nguyên tắc 3: So sánh Estimated vs Actual Rows
Nếu ước lượng sai nghiêm trọng → SQL có thể chọn sai chiến lược join → query chậm.
3. Các Operator Quan Trọng Nhất
3.1 Table Scan (Nguy hiểm với bảng lớn)
SQL quét toàn bộ bảng.
Xảy ra khi:
Không có index phù hợp
WHERE không SARGable
Implicit conversion
Với bảng vài triệu record → rất tốn I/O.
3.2 Index Seek (Tối ưu)
SQL tìm đúng vị trí dữ liệu trong index.
Luôn muốn thấy Seek thay vì Scan.
3.3 Index Scan
Quét toàn bộ index. Tốt hơn Table Scan nhưng vẫn là quét toàn bộ.
3.4 Key Lookup (I/O killer)
Xảy ra khi:
SQL dùng index để tìm key
Nhưng cần thêm cột không có trong index
Phải quay lại clustered index để lấy dữ liệu
Nếu xảy ra hàng chục nghìn lần → rất chậm.
Giải pháp: tạo Covering Index.
3.5 Nested Loop
Tốt khi:
Một bảng nhỏ
Bảng còn lại có index
3.6 Hash Match
Thường dùng khi:
Join bảng lớn
Không có index tốt
Tốn RAM. Có thể spill ra tempdb.
3.7 Sort
Sort tốn CPU và memory. Nếu không có index theo ORDER BY, SQL buộc phải sort.
Đọc đầy đủ bài viết ở link comment.