Індекс допомагає лише тоді, коли умова записана так, що MySQL може шукати безпосередньо за значенням колонки. Найчастіші причини, чому це не так:
1. Функція чи вираз над колонкою.
-- індекс на created_at не використовується
WHERE YEAR(created_at) = 2026
WHERE DATE(created_at) = '2026-10-04'
WHERE price * 1.2 > 100
-- переписати на діапазон по «голій» колонці
WHERE created_at >= '2026-01-01' AND created_at < '2027-01-01'
WHERE price > 100 / 1.2
Якщо без функції ніяк, у MySQL 8 є функціональні індекси: CREATE INDEX ... ((LOWER(email))).
2. Неявне приведення типів. Рядкова колонка порівнюється з числом:
-- phone VARCHAR(20), індекс є
WHERE phone = 380501234567 -- кожен рядок перетворюється на число, індекс не працює
WHERE phone = '380501234567' -- індекс працює
Навпаки (числова колонка, рядкова константа) - не страшно: перетворюється константа. Те саме при з'єднаннях: колонки різних типів чи різних кодувань у JOIN можуть позбавити індексу.
3. LIKE з відсотком на початку.
WHERE name LIKE 'Олек%' -- діапазон індексу, працює
WHERE name LIKE '%сандр%' -- немає початку, з якого шукати
Для пошуку всередині тексту - FULLTEXT-індекс чи зовнішній пошуковий рушій.
4. Порушене правило лівого префікса складеного індексу: умова не містить першої колонки.
5. OR між різними колонками. WHERE email = ? OR phone = ? може взагалі не використати індекс або використати злиття індексів. Інколи краще UNION двох запитів.
6. Оптимізатор вирішив, що повне сканування дешевше. Якщо умова підходить під значну частину таблиці (наприклад, status = 'active' для 80% рядків), читати таблицю послідовно швидше, ніж робити тисячі переходів з індексу в кластерний індекс. Це не помилка, а правильне рішення.
7. Застаріла статистика. Після масового завантаження оцінки можуть бути хибними - допомагає ANALYZE TABLE.
Як перевіряти: завжди через EXPLAIN на реалістичному обсязі даних. На таблиці зі ста рядків MySQL обиратиме повне сканування, і висновки будуть хибними.