Підказки індексів дають оптимізатору вказівки, які індекси розглядати:
SELECT * FROM orders USE INDEX (orders_user_idx) WHERE user_id = 7 AND status = 'paid';
SELECT * FROM orders FORCE INDEX (orders_created_idx) WHERE created_at > '2026-09-01';
SELECT * FROM orders IGNORE INDEX (orders_status_idx) WHERE status = 'paid';
USE INDEX- розглядати лише вказані індекси (але повне сканування лишається можливим);FORCE INDEX- якUSE INDEX, але повне сканування вважається дуже дорогим: індекс буде використано, якщо це взагалі можливо;IGNORE INDEX- не розглядати вказані індекси.
Можна уточнити призначення: FOR JOIN, FOR ORDER BY, FOR GROUP BY.
У Laravel для цього є методи будівника:
Order::query()->forceIndex('orders_created_idx')->where('created_at', '>', $date)->get();
Order::query()->useIndex('orders_user_idx')->...;
Order::query()->ignoreIndex('orders_status_idx')->...;
Чому це крайній засіб:
- підказка заморожує рішення, ухвалене на сьогоднішніх даних. Через рік розподіл зміниться, а запит і далі змушений використовувати індекс, який уже невигідний;
- перейменування чи видалення індексу ламає запит: на неіснуючий індекс у підказці MySQL поверне помилку;
- підказка маскує справжню причину: застарілу статистику, неселективний індекс, невдало записану умову;
- запит прив'язується до MySQL - на PostgreSQL чи SQLite (у тестах) такий синтаксис не працює. Laravel-методи на інших драйверах ігноруються або генерують свої варіанти, тож поведінка розходиться.
Що спробувати перед підказкою:
ANALYZE TABLE- оновити статистику;- гістограма на колонці з нерівномірним розподілом;
- кращий складений індекс, під який запит природно підходить;
- переписати умову (прибрати функцію з колонки, розбити
ORнаUNION); - прибрати зайві схожі індекси, між якими оптимізатор «вагається».
Майбутнє синтаксису. Документація MySQL 8.4 попереджає, що USE INDEX, FORCE INDEX і IGNORE INDEX планують оголосити застарілими на користь оптимізаторних підказок у коментарях: /*+ INDEX(orders orders_created_idx) */ і /*+ NO_INDEX(...) */, плюс точніші JOIN_INDEX, ORDER_INDEX, GROUP_INDEX. Новий код краще писати одразу з ними.
Коли підказка виправдана: відомий патологічний запит, де оптимізатор стабільно помиляється, і всі інші варіанти перевірено. Тоді варто лишити коментар, чому вона тут, - і переглядати після оновлень MySQL.