Почему MySQL выполняет fileort по этому запросу? Я просто ожидаю, Using where
:
SELECT * FROM active_campaign_days
WHERE ad_unit_id=1
AND day='2017-12-10'
ORDER BY bid DESC, budget DESC, campaign_id ASC
Индекс на (ad_unit_id, day, bid, budget, campaign_id)
- база данных использует этот индекс в соответствии с EXPLAIN
.
В этом конкретном наборе результатов bid
и budget
одинаковы для всех строк. (ad_unit_id, campaign_id)
уникален.
EXPLAIN:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE active_campaign_days ref ad_unit_id,ad_unit_id_2 ad_unit_id_2 7 const,const 5 Using where; Using filesort
Пусть разрешит запрос.
WHERE ad_unit_id=1 AND day='2017-12-10'
нуждается в индексе, начинающемся с ad_unit_id
и в day
(в любом порядке). Это обеспечит оптимальную фильтрацию.
Если это практично, все ORDER BY
могут быть добавлены к этому INDEX
чтобы избежать необходимости сортировать данные. Но есть проблема с ORDER BY bid DESC, budget DESC, campaign_id ASC
. Обратите внимание, что существует смесь DESC
и ASC
. MySQL может только сканировать индекс в одном направлении. Это означает, что все должно быть ASC
или все должно быть DESC
. (См. Примечание ниже) Итак, INDEX(ad_unit, day, bid, budget, campaign_id)
не так полезен, как вам хотелось бы.
Если Оптимизатор может пройти мимо шага 2, добавив любые другие столбцы, упомянутые где угодно в SELECT
(а именно все *
), тогда индекс будет "закрыт". Это дает различные возможности повышения производительности - выполняя всю работу в индексе, не касаясь "данных".
Примечание. Начиная с версии 8.0, MySQL будет DESC
в объявлениях индексов. Таким образом, вы можете INDEX(ad_unit, day, bid DESC, budget DESC, campaign_id ASC)
, и оптимизатор может использовать его без сортировки в пункте 2 выше. (Pre-8.0, DESC
разрешалось, но игнорировалось, в объявлениях индексов.)
Обходной путь? Он изменит порядок вывода, но вы можете принять все столбцы ASC
(или все DESC
)?
Между тем, INDEX(ad_unit_id, day)
- это все, что стоит иметь.