Column Transformation - Sai lầm #1 khiến index bị “mù”

Bất kỳ phép biến đổi nào áp dụng LÊN CỘT (không phải lên giá trị) đều khiến index vô dụng.

-- ❌ Hàm trên cột → index trên birthday VÔ DỤNG
SELECT * FROM contacts WHERE YEAR(birthday) = 1988;
-- Database thấy: YEAR(birthday) là một biểu thức, không phải cột birthday
-- Index lưu '1988-03-15', '1990-07-22'... không phải 1988, 1990 → không map được!
 
-- ✅ Viết lại: dùng range condition trên cột gốc
SELECT * FROM contacts
WHERE birthday >= '1988-01-01' AND birthday < '1989-01-01';

Tại sao database không tự rewrite? Vì phải xử lý mọi tổ hợp hàm có thể - cực phức tạp và dễ sai. Nguyên tắc giữ đơn giản: biến đổi cột = không dùng index. Không ngoại lệ.

Các trường hợp hay gặp

WHERE col + 5 < 20                       → ✅ WHERE col < 15
WHERE CONCAT(first,' ',last)='Huy Nguyen' → ✅ WHERE first='Huy' AND last='Nguyen'
WHERE varchar_col = 12345 (type juggling) → ✅ WHERE varchar_col = '12345'
WHERE DATE(created_at) = '2024-01-15'
   → ✅ WHERE created_at >= '2024-01-15' AND created_at < '2024-01-16'
WHERE LOWER(email) = '[email protected]'   → ✅ Dùng functional index

Quy tắc phân biệt

Biến đổi trên GIÁ TRỊ thì an toàn (database tính trước rồi so sánh); biến đổi trên CỘT thì phá index. WHERE age = '25' với age INT vẫn ổn - MySQL chuyển ‘25’ → 25 trên giá trị.

Khi KHÔNG THỂ viết lại query

WHERE MONTH(birthday) = 5 (tháng 5 của mọi năm) không thể chuyển thành range → dùng Functional Index.

Liên quan