Biến Range thành Equality (Biến đổi điều kiện phạm vi)
Nếu biến range condition thành so sánh bằng, hạn chế “range phá vỡ phễu” biến mất.
Bài toán
SELECT * FROM repos
WHERE language = 'TypeScript' AND stars > 1000
ORDER BY sponsors ASC;
-- Phương án 1: Index (language, stars, sponsors)
-- → range bắt đầu ở stars → sponsors KHÔNG được sắp xếp liên tục
-- → phải sắp xếp lại sau khi lấy kết quả (filesort)
-- Phương án 2: Index (language, sponsors) bỏ qua stars
-- → sort đúng nhưng phải quét toàn bộ TypeScript rồi lọc stars
-- Cả hai đều không lý tưởng!Ý tưởng: thay vì hỏi “bao nhiêu sao?” → hỏi “có phổ biến không?” (0 hoặc 1)
-- Tạo index trên biểu thức boolean
CREATE INDEX repos_search ON repos (
language,
(IF(stars > 1000, 1, 0)), -- boolean: phổ biến hay không
sponsors -- sắp xếp
);
-- Query dùng đúng biểu thức
SELECT * FROM repos
WHERE language = 'TypeScript'
AND IF(stars > 1000, 1, 0) = 1
ORDER BY sponsors ASC;
-- Phễu hoạt động hoàn hảo:
-- Bước 1: language = 'TypeScript' (equality)
-- Bước 2: is_popular = 1 (equality)
-- Bước 3: đọc theo sponsors tăng dần (đã sắp xếp sẵn!) → KHÔNG cần filesortKhi nào dùng kỹ thuật này?
Khi query có cả lọc range lẫn sắp xếp, và điều kiện range có thể rút gọn thành “có/không” theo logic nghiệp vụ:
- “giá trên 100k” →
is_expensive - “đăng ký trên 1 năm” →
is_veteran - “đánh giá trên 4 sao” →
is_highly_rated
Kỹ thuật này cũng cứu GROUP BY + WHERE range: tạo cột age_group='twenties' rồi WHERE age_group='twenties' → equality → phễu tiếp tục hoạt động.
Liên quan
- Range Condition phá vỡ Phễu - hạn chế gốc
- Functional Index - công cụ hiện thực hóa
- Virtual Column - cách làm trên MariaDB/SQL Server
- Ghost Condition - kỹ thuật “chị em”: thêm điều kiện thừa giúp index