Vấn đề: COUNT DISTINCT chậm trong MySQL
Khi thực hiện truy vấn COUNT(DISTINCT column) trên bảng lớn, MySQL thường quét toàn bộ bảng hoặc chỉ mục, dẫn đến hiệu suất kém. Giải pháp tối ưu hóa là tạo chỉ mục phù hợp.
Giải pháp: Sử dụng chỉ mục tổ hợp (Composite Index)
Tạo chỉ mục trên các cột thường xuyên xuất hiện trong mệnh đề DISTINCT hoặc GROUP BY. Ví dụ dưới đây minh họa việc tạo chỉ mục trên hai cột FirstName và LastName.
1. Tạo bảng với chỉ mục
CREATE TABLE DemoTable (
FirstName VARCHAR(20),
LastName VARCHAR(20),
INDEX idx_fullname (FirstName, LastName)
);
2. Chèn dữ liệu mẫu
INSERT INTO DemoTable VALUES
('John', 'Smith'),
('John', 'Doe'),
('Adam', 'Smith'),
('John', 'Doe'),
('Chris', 'Brown'),
('Adam', 'Smith');
3. Truy vấn COUNT DISTINCT
SELECT COUNT(DISTINCT FirstName) FROM DemoTable;
4. Kết quả
+---------------------------+
| COUNT(DISTINCT FirstName) |
+---------------------------+
| 3 |
+---------------------------+
Tại sao chỉ mục giúp tăng tốc?
- Chỉ mục
idx_fullnamelưu trữ các giá trị duy nhất của cặp(FirstName, LastName)theo thứ tự đã sắp xếp. - MySQL có thể duyệt chỉ mục thay vì quét toàn bảng, giảm I/O đĩa và thời gian CPU.
- Đặc biệt hiệu quả khi số lượng giá trị duy nhất ít so với tổng số hàng.
Lưu ý quan trọng
- Chỉ mục tổ hợp chỉ tối ưu khi truy vấn dùng đúng thứ tự cột (trái sang phải).
- Với
COUNT(DISTINCT col1, col2), chỉ mục trên(col1, col2)hiệu quả nhất. - Tránh tạo quá nhiều chỉ mục không cần thiết – chúng làm chậm
INSERT/UPDATE.
Kiểm tra kế hoạch thực thi
Sử dụng EXPLAIN để xác nhận MySQL sử dụng chỉ mục:
EXPLAIN SELECT COUNT(DISTINCT FirstName) FROM DemoTable;
Kết quả mong muốn: cột type hiển thị index hoặc ref, Extra có Using index.