Індекс зберігає значення колонки в певному порядку. Якщо умова перетворює колонку, база шукає вже не ці значення, і звичайний індекс не допомагає:
WHERE lower(email) = 'ivan@x.com' -- індекс на email не використається
WHERE DATE(created_at) = '2026-10-04' -- те саме
WHERE name LIKE '%олег%' -- невідомий початок рядка
Як виправити:
- Переписати умову, щоб колонка лишалася «голою»:
WHERE created_at >= '2026-10-04' AND created_at < '2026-10-05'
- Індекс за виразом (PostgreSQL; функціональний індекс у MySQL 8.0.13+):
CREATE INDEX users_email_lower_idx ON users (lower(email));
LIKE 'олег%'(відомий початок) працює з B-деревом. У PostgreSQL з не-C локаллю для цього потрібен індекс зtext_pattern_ops.LIKE '%олег%'- потрібен інший тип індексу: триграмний (pg_trgm+ GIN у PostgreSQL) або повнотекстовий пошук (tsvector,FULLTEXTу MySQL), або окремий пошуковий рушій - Meilisearch, Elasticsearch.
Ще одна пастка - неявне приведення типів: порівняння рядкової колонки з числом (WHERE phone = 380501234567) змушує MySQL перетворювати кожне значення колонки, і індекс не працює.