Câu 1Vì sao Index-Only Scan tránh quay về bảng nền?
Index-Only Scan — Chỉ mục bỏ qua bảng
Bài viết này là một phần của Khóa học SQL, giúp bạn thành thạo từ đầu những kỹ năng SQL thực tiễn, từ cơ bản đến các truy vấn phức tạp và tối ưu hóa SQL.
Đưa mọi cột truy vấn chạm vào chỉ mục và chuyến quay về bảng nền biến mất. Đây là Index-Only Scan (còn gọi là covering index). Bạn sẽ học các điều kiện làm nó hoạt động, cách nó hỏng ngay khi thiếu một cột, và cách gấp các cột bộ lọc WHERE vào một chỉ mục duy nhất, tất cả xác minh với EXPLAIN QUERY PLAN.
Bỏ qua tra cứu bảng — Index-Only Scan
Tra cứu chỉ mục thông thường tìm dòng đích trong chỉ mục, rồi quay về bảng nền để đọc các cột khác từng dòng một.
Chuyến quay về này gọi là table lookup (bước lấy một dòng từ bảng nền qua chỉ mục).
Khi tập kết quả lớn, các chuyến đi vòng đó dồn lại và bắt đầu tốn thời gian thực.
Nếu bạn dùng chỉ mục chứa mọi cột truy vấn tham chiếu, mọi giá trị đều ở ngay trong chỉ mục, và không cần quay về bản thân bảng.
Mẫu này, nơi chỉ mục một mình đưa ra kết quả, gọi là Index-Only Scan (chỉ mục bao mọi cột truy vấn chạm vào còn gọi là covering index).
-- Tổng hợp region với chỉ mục chỉ chứa region
-- Cột được tham chiếu (region) hoàn toàn ở trong chỉ mục → không chuyến quay về bảng nền
DROP INDEX IF EXISTS ix_demo;
CREATE INDEX ix_demo ON perf_sales(region);
EXPLAIN QUERY PLAN
SELECT region, COUNT(*)
FROM perf_sales
GROUP BY region;
Thiếu một cột và bạn quay về bảng nền
Index-Only Scan chỉ xảy ra khi mọi cột truy vấn chạm vào — trong SELECT, WHERE, GROUP BY, vv. — ở trong chỉ mục.
Thiếu một cột và cơ sở dữ liệu phải quay về bảng nền để đọc nó, và USING COVERING INDEX biến mất khỏi kế hoạch.
Ví dụ, với chỉ mục trên (emp_id, amount), viết SELECT emp_id, SUM(amount), region thêm region, không có trong chỉ mục — nên truy vấn quay về bảng nền để lấy nó.
-- Với chỉ mục trên (region, amount),
-- thêm product vào các cột được tham chiếu phá Index-Only Scan
DROP INDEX IF EXISTS ix_demo;
CREATE INDEX ix_demo ON perf_sales(region, amount);
-- region, SUM(amount) chỉ → bao trọn bởi chỉ mục
EXPLAIN QUERY PLAN
SELECT region, SUM(amount) FROM perf_sales GROUP BY region;
-- Thêm product → không có trong chỉ mục, nên quay về bảng nền
EXPLAIN QUERY PLAN
SELECT region, SUM(amount), MAX(product) FROM perf_sales GROUP BY region;
Giữ Index-Only Scan bằng cách bao cả cột bộ lọc WHERE
SELECT không phải nơi duy nhất cột xuất hiện trong truy vấn của bạn.
Cột bộ lọc WHERE cũng tính là cột truy vấn chạm vào, nên chúng cần ở trong chỉ mục — nếu không bạn vẫn quay về bảng nền.
Gấp tất cả vào một chỉ mục theo thứ tự "cột bộ lọc → cột đầu ra / tổng hợp", và cả việc lọc lẫn lấy giá trị kết thúc trong cùng chỉ mục.
Ví dụ, để lọc với WHERE region = 'East' và tính SUM(amount), đặt cột bộ lọc region trước và cột tổng hợp amount sau: (region, amount).
Chỉ mục thu hẹp về các dòng đích theo region và đọc amount từ cùng chỉ mục, nên không cần chuyến quay về bảng nền.
-- Gấp cột bộ lọc (status) và cột tổng hợp (amount) vào một chỉ mục
DROP INDEX IF EXISTS ix_demo;
CREATE INDEX ix_demo ON perf_sales(status, amount);
EXPLAIN QUERY PLAN
SELECT SUM(amount)
FROM perf_sales
WHERE status = 'pending';
Kiểm tra kiến thức
Hãy trả lời từng câu hỏi một.
Câu 2Với chỉ mục trên (emp_id, amount), truy vấn nào phá Index-Only Scan và quay về bảng nền?
Câu 3Với truy vấn lọc bằng WHERE region = 'East' và tính SUM(amount), chỉ mục nào hỗ trợ Index-Only Scan?