Какая версия MySQL / MariaDB? Недавно были оптимизации. не сейчас, если они помогут здесь.
У вас есть возможная ошибка - в том числе дополнительный день в AND expiry_date BETWEEN '2017-01-01' AND '2018-01-01'
. Изменить на
AND expiry_date >= '2017-01-01'
AND expiry_date < '2017-01-01' + INTERVAL 1 YEAR
(Это считается одним тестом «диапазона». BETWEEN
также является тестом диапазона, но это «включительно», следовательно, «ошибка».)
У меня просто было бы два составных индекса (если бы я не мог найти реальный ответ на ваш вопрос):
(group_id, type_id, expiry_date)
(group_id, expiry_date)
Случай 1: Оптимизатор может пройти мимо IN
: тогда работает первый индекс.
Случай 2: оптимизатор не может пройти мимо IN
: Тогда происходит одно из следующих действий:
- В списке
IN
есть только один элемент. Затем он преобразуется из IN
в =
, и первый индекс является оптимальным, при этом используются все 3 столбца.
- Оптимизатор решает, что первый индекс лучше - маленький список IN, большой диапазон дат.
- Оптимизатор решает, что диапазон дат лучше (меньший диапазон), и выбирает второй индекс.
Подход UNION
может или не может быть лучше в этой ситуации. Сбор данных во временную таблицу требует много времени. Временная таблица была недавно удалена, но только для некоторых случаев UNION ALL
.
Да, используйте UNION ALL
. Это исключает сортировку и, возможно, дополнительную временную таблицу.
Тест с большим набором данных. Для строк размером менее 1 КБ производительность вряд ли будет иметь значение.
Правило большого пальца в упорядочении столбцов в индексе:
=
тест (ы)
IN
, если есть
- один «диапазон» (
BETWEEN
, <
и т. Д.), Если есть
- Подумайте о создании индекса покрытия.
Мой Кулинарная книга
Существуют другие оптимизации, которые зависят от того, что находится в *
в SELECT *
.